
<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[DotMH Dev Articles]]></title><description><![CDATA[I am a Senior Full Stack Engineer with over 17 years of experience. I have worked in a variety of industries providing technical and design work, as well as tec]]></description><link>https://articles.dotmh.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1744895543127/3395cc67-181b-4cdb-84b4-ef78dc294b6c.png</url><title>DotMH Dev Articles</title><link>https://articles.dotmh.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Sat, 23 May 2026 11:59:37 GMT</lastBuildDate><atom:link href="https://articles.dotmh.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Learning C# in 2025]]></title><description><![CDATA[The Why?
I try to regularly learn a new programming language, the reason for this can best be summed up with this quote from the Pragmatic Programmer

Different languages solve the same problems in different ways. By learning several different approa...]]></description><link>https://articles.dotmh.dev/learning-c-in-2025</link><guid isPermaLink="true">https://articles.dotmh.dev/learning-c-in-2025</guid><category><![CDATA[learning]]></category><category><![CDATA[C#]]></category><category><![CDATA[.NET]]></category><dc:creator><![CDATA[Martin Haynes]]></dc:creator><pubDate>Thu, 25 Sep 2025 15:48:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/505eectW54k/upload/e7faba071c82e840464ad07339c48184.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-the-why">The Why?</h2>
<p>I try to regularly learn a new programming language, the reason for this can best be summed up with this quote from the <a target="_blank" href="https://amzn.eu/d/bCjcAYx">Pragmatic Programmer</a></p>
<blockquote>
<p><strong>Different languages solve the same problems in different ways. By learning several different approaches, you can help broaden your thinking and avoid getting stuck in a rut. Additionally, learning many languages is far easier now, thanks to the wealth of freely available software on the Internet.</strong></p>
</blockquote>
<p>This year, I decided to learn C# and, in extension, the .NET Framework. There were several reasons for this, but the primary motivation was to access a language that was similar to lower-level languages like C, C++, and Rust. Using C# as a stepping stone to move to these lower languages, but with the convenience of the high-level constructs and easier syntax.</p>
<p>I had not been particularly interested in learning C# as it was tied to Microsoft Windows, that is, until 2014, when Microsoft decided to open-source the project. In the ten years since that release, .NET has invested considerable effort in becoming a truly cross-platform platform.</p>
<p>Another reason is that my daily language is TypeScript, as I mentioned in previous posts. TypeScript’s lead architect is <a target="_blank" href="https://articles.dotmh.dev/my-development-heroes#heading-anders-hejlsberg">Anders Hejlsberg</a>, the same lead architect as C#.</p>
<p>The last reason for learning C# is that it can be used by Godot and other game engines, as well as bindings to frameworks like SDL3 and Raylib. I have a keen interest in game development; having knowledge of the language would allow me to develop my own games, whether using or without those engines.</p>
<h2 id="heading-the-how">The How!</h2>
<p>When you are an experienced developer, finding resources for a new language can be a challenge. This is because many language learning resources are designed with beginners in mind. This is brilliant, don’t get me wrong, getting people into software development grows the pool of programmers and innovation. The downside of this, as a senior developer, is that there is a significant amount of duplicated information. I am familiar with the fundamentals of programming, including data types, control flow, and object-oriented programming.</p>
<p>With this in mind, I used the following in order to learn C#.</p>
<h3 id="heading-c-12-pocket-reference"><strong>C# 12 Pocket Reference</strong></h3>
<p>This is a <a target="_blank" href="https://www.amazon.co.uk/12-Pocket-Reference-Instant-Programmers/dp/1098147545?crid=28IRD5IPJV6K3&amp;dib=eyJ2IjoiMSJ9.QexFY6Z7heMOZ76bi8e_BRaTLC0HiPm92ykK-MgY0RzXAJwq8x7BpPaOMD4TKOHJ0ZmrEj1WN62SL05lOHQveVOdEpsxfTzR1i15HzxbvrzDTPLEM2OoTz-x6Hq__c1Qzy-_z7URiuyMfX1wfXOx7Vmp8HIoDSjOV08XzK8ysQoV45_baI2gGVVZsLg_t2fuQ_VWh4oOGetxvOjsxr7DFaQdIxvUXPfIsZYRyHwBDxA.vmwygz_g8NAnK0EdR6-G8k2PfewoCz0EDVqT8Gka1YU&amp;dib_tag=se&amp;keywords=C%23&amp;qid=1758795242&amp;sprefix=c%23,aps,109&amp;sr=8-18">book</a> from O’Reilly, where many books attempt to provide the reader with both programming and language information for the language they are teaching; the Pocket Reference is simply that —a reference to the language. I make a point of reading a section of this book every day. This gives me an idea of what the C# language is capable of. What features and paradigms can I use when building software? It doesn’t go into detail about them, however, but for that, it is a compromise I can work with, as I can often find more detailed information from other sources. I use this book more as an index of the tools I have in the C# toolbox, rather than a user's guide to those tools, although it will contain all the simple concepts I need.</p>
<h3 id="heading-jetbrains-rider">Jetbrains Rider</h3>
<p><a target="_blank" href="https://www.jetbrains.com/rider/">JetBrains Rider</a> is an IDE from JetBrains designed for the .NET ecosystem, incorporating some of the best tools. These tools include ReSharper, dotPeek, dotCover, dotTrace, and dotMemory, all of which are available in a single IDE. If you are accustomed to JetBrains tooling, this setup will be very familiar to you. This makes it easy to get started with building projects, as all the tooling is made available in an easy-to-use and visual manner. Of course, all this can be done through the command line tooling provided by .NET with the <code>dotnet</code> command.</p>
<h3 id="heading-linq-pad">LINQ Pad</h3>
<p><a target="_blank" href="https://www.linqpad.net/">LINQ Pad</a> is a tool designed as a playground for .NET and <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/standard/linq/">LINQ,</a> which is a built-in SQL-like language in .NET. It supports the major .NET CLI languages, including Visual Basic, F#, and, of course, the one I am interested in, C#. The basic tool is free; unfortunately, the free version is missing NuGet (.NET version of tools like NPM) support, which limits its usefulness beyond basic use. I quickly upgraded my version to Developer to get the extras, including the NuGet support. This allows me to build small code blocks to experiment with ideas and concepts without needing to spin up a full .NET project.</p>
<h3 id="heading-github-co-pilot">Github Co-Pilot</h3>
<p>This might be slightly controversial, but I have found Copilot really handy. I have been very disciplined when using it; however, I don’t want to vibe code in C#. I want to learn. I have a rule when adding code to a project that I don’t directly author, whether it comes from Stack Overflow, GitHub, a blog, Copilot, or anywhere else: I won't add it unless I understand it. This means that if I do use Copilot, I review what it's suggesting, try to understand why it is doing it, and consider what it is doing before adding it. This means that I do learn and improve my C# when using Copilot. The other thing I will use it for is a semi-smart search tool, so I will ask it things like “how do I check the type of a generic?”, “How do I load a mock from a file in an XUnit test?” or “How do I get a list of all environment variables?”.</p>
<h3 id="heading-writing-code">Writing Code</h3>
<p>The only way to learn a new language is to write it, and to write lots of it. If you don’t work with the language and the ecosystem (and the .NET ecosystem is massive), you won't learn and develop skills in that language. So, I write projects and ideas that have been floating around in my head, and I start building them in C# instead of a language with which I am more familiar. The same goes if I need a small tool or service; I will build it in C# instead of Typescript. Every line of code I write in C# or problem I solve teaches me something. I also write tests for everything; this is not only good practice but also helps build more familiarity with the language. To that end, I created a new <a target="_blank" href="https://github.com/dotmh/dotnet">template</a> in GitHub to make spinning up projects even more effortless, allowing me to write more code.</p>
<h2 id="heading-what-is-next">What is next</h2>
<p>I am just at the beginning of my journey learning C# and the .NET ecosystem. I find writing code in C# to be very nice, and the fact that I can run it pretty much anywhere is quite cool. I plan to keep learning C# for the time being. I want to build more project types, such as audio, GUI, api applications, as well as build games. I am hoping to add it to my toolbox for solving problems in the future, so expect more posts on my C# adventures.</p>
]]></content:encoded></item><item><title><![CDATA[Learn Together™]]></title><description><![CDATA[Why?
Every good company should invest in its employees’ skills; your people are a resource, and just like any other resource, you must invest in them. Now, most companies understand this and put aside money for training. This training can take many f...]]></description><link>https://articles.dotmh.dev/learn-together</link><guid isPermaLink="true">https://articles.dotmh.dev/learn-together</guid><category><![CDATA[learning]]></category><category><![CDATA[training]]></category><category><![CDATA[#learntogether]]></category><category><![CDATA[skills]]></category><category><![CDATA[upskilling]]></category><category><![CDATA[team collaboration]]></category><dc:creator><![CDATA[Martin Haynes]]></dc:creator><pubDate>Wed, 21 May 2025 23:00:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/kscOvVLq2fk/upload/c154eb523b84b906327a452a5ff1930a.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-why">Why?</h1>
<p>Every good company should invest in its employees’ skills; your people are a resource, and just like any other resource, you must invest in them. Now, most companies understand this and put aside money for training. This training can take many forms, including instructor-led training, both in-person and online, self-paced training, and book-based training, all of which I have seen being deployed. This is great, allowing your staff to choose a training method that fits them and how they learn is the best way to achieve results.</p>
<p>However, a resource that often gets overlooked is your team. Your team will include individuals with diverse skillsets and experiences that can be valuable to others. The advantages of utilising this knowledge are many, and it can provide higher-quality results than other training methods with less investment.</p>
<p>One of the most apparent advantages is that it can reduce the <a target="_blank" href="https://en.wikipedia.org/wiki/Bus_factor">bus factor</a> if you have people with particular knowledge. Sharing this knowledge across the team means it is already known, should the worst happen. You may, however, encounter pushback from toxic individuals who see having knowledge only known to them as ensuring job security or want to gatekeep that knowledge. Unfortunately, you may have to address these behaviours with those individuals through your existing HR process first.</p>
<p>Another advantage of using the knowledge in the team is that they will have more domain knowledge. They know your business, its process, users, and tech stack. This means that things as simple as examples, as well as topics covered, are being tailored. This will give you higher-quality training and reduce the time to learn for participants. This is also good at forming a common language within your teams.</p>
<p>This training style isn’t always possible, possibly due to regulatory or legal requirements or because your team may not be comfortable leading training. As you can tell, if you follow me or have worked with me, I enjoy sharing my knowledge and expertise with others. Even though I found it very difficult to start doing that within a new team, it has helped my learning, and explaining something to someone else is a great way to validate your understanding of the topic.</p>
<p>Although I have covered the advantages of Learn Together™, it shouldn’t be the only training provided. You may have to look at other options if your team doesn’t know a specific area. Learn Together™ can also be a great starting point for topics, and then individual team members may want to learn more through more traditional training avenues. It can also help to look at cross-team training opportunities. A team may already have expertise in an area that another team needs.</p>
<h1 id="heading-how">How?</h1>
<p>So, how do you use Learn Together™ in your organisation? Well, I can’t say for sure, I was lucky when I started it, I wanted to share my knowledge and expertise with the team, the team wanted to learn, and my manager was open to the idea.</p>
<p>I will review how we do Learn Together™ if anyone finds it useful. So a learn together session has no fixed length, and that more casual flexibility, I think, makes it work for the team. I will schedule a session once a <a target="_blank" href="https://www.atlassian.com/agile/scrum/sprints">sprint</a> (our sprint cadence is two weeks), generally in the second week. One thing I make sure to emphasise is that these sessions are entirely optional. The idea is that team members can choose to attend sessions they find interesting or valuable. I typically book the session for at least 30 minutes but up to an hour. I don’t feel that anything longer than an hour-long session is helpful, as it causes fatigue in both the trainer and the students and can conflict with team priorities.</p>
<p>When running a session, I will try to keep it casual and use as many examples, workshops, and demos as possible to keep people engaged. As mentioned above, because I am aware of the business, its technology, process, and goals, I can keep these demos relevant, which makes them much more helpful to the team. These tips are more about how people want to learn, but I believe these methods are better suited to the Learn Together™ format, rather than lecturing or presentation-based learning. Not all topics will work with this format, so you may need to explore other methods depending on the subject.</p>
<p>After a session, I will write an overview of what was covered in our knowledge platform. This will provide a reference for those who attended and those who could not. It will also help me track what has been discussed when planning new sessions and topics, so they are not required to be covered again when building on previous sessions.</p>
<p>The most significant barrier to getting started is finding someone prepared to champion the Learn Together™ format. If that is you, that is great, but you may struggle if you are looking for someone else to do it. If you are not a manager, make sure to get manager buy-in; you will need to use up to an hour of the team’s time regularly, which is easier if the manager scheduling the team’s work is aware.</p>
<p>I have also found it essential to try to involve other team members as the trainer who may have more knowledge than you on a topic. This allows others to grow and shows you what it is like to be a student and a trainer. This will make it easier to tailor your teaching to your team and their needs.</p>
<p>In summary</p>
<ul>
<li><p>Be the champion, or find someone who will.</p>
</li>
<li><p>Keep the sessions under an hour.</p>
</li>
<li><p>Use demos, Workshops and examples.</p>
</li>
<li><p>Keep it casual.</p>
</li>
<li><p>Make sure people are aware it is optional.</p>
</li>
<li><p>Try to do it regularly.</p>
</li>
<li><p>Reinforce the learning with a write-up post-session.</p>
</li>
<li><p>Involve other team members, especially if they are keen to get involved.</p>
</li>
</ul>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">The ™ on Learn Together™ is an inside joke. I do not own a trademark for the phrase, and you can use it.</div>
</div>]]></content:encoded></item><item><title><![CDATA[Typescript Type Narrowing And Assertions]]></title><description><![CDATA[This week, we're getting a bit more technical and a bit more into the weeds of TypeScript. This covers how the typescript handles types and behaves when converting from one type to another. Along with the basics of how this works, it also covers what...]]></description><link>https://articles.dotmh.dev/typescript-type-narrowing-and-assertions</link><guid isPermaLink="true">https://articles.dotmh.dev/typescript-type-narrowing-and-assertions</guid><category><![CDATA[TypeScript]]></category><category><![CDATA[TypeSafety]]></category><category><![CDATA[assertion]]></category><dc:creator><![CDATA[Martin Haynes]]></dc:creator><pubDate>Tue, 13 May 2025 08:54:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/c8jYxRgu3UU/upload/31e7874f4ebed5e70bcd82c3311730f7.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This week, we're getting a bit more technical and a bit more into the weeds of <a target="_blank" href="https://www.typescriptlang.org/">TypeScript</a>. This covers how the typescript handles types and behaves when converting from one type to another. Along with the basics of how this works, it also covers what you can do to make this narrowing more robust.</p>
<p>Typescript is a compile-time tool that adds a type system to JavaScript. Typescript does not affect runtime; all type information is discarded during the build/compile process.</p>
<p>Built on JavaScript, TypeScript inherits all of JavaScript's types. As JavaScript is loosely typed, JavaScript will try its best to do type conversion for you, using a process called <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/Type_coercion">coercion</a>; therefore, JavaScript does have types, and these types form the foundation types in TypeScript.</p>
<p>Typescript uses a hierarchical type system, meaning one type can extend from another.</p>
<h1 id="heading-types">Types</h1>
<p>The base types in the hierarchy are</p>
<h2 id="heading-extendable">Extendable</h2>
<p>All these can have child types that extend from them</p>
<ul>
<li><p>String - any value that represents a string of characters</p>
</li>
<li><p>Number - any number, both whole and decimal, from 0 to <code>Number.MAX_VALUE</code></p>
</li>
<li><p>Boolean - the values true or false</p>
</li>
<li><p>Object - An object literal or anything that extends object literals. <em>Note that Arrays in JavaScript are objects.</em></p>
</li>
</ul>
<h2 id="heading-not-extendable">Not Extendable</h2>
<p>These can not have any child types</p>
<ul>
<li><p>undefined - only contains the value undefined, this is a special type that means that a variable does not exist or has had its value</p>
<p>  explicitly set to undefined, or has not had a value set (implicitly set to undefined)</p>
</li>
<li><p>null - only contains the value null, a special type that means a variable has been defined but has had its value explicitly set to null.</p>
</li>
</ul>
<h2 id="heading-typescript-types">Typescript Types</h2>
<p>JavaScript does not use these base types, so they are unavailable at runtime, only at compile time when using TypeScript. None of these types can be extended from</p>
<h3 id="heading-never">Never</h3>
<p>This special type tells TypeScript that if code ever reaches this, something has gone wrong, i.e. you should never have a path to this type.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> runtimeError = (): <span class="hljs-function"><span class="hljs-params">never</span> =&gt;</span> {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Something went wrong"</span>);
}
</code></pre>
<p>This is never used because if this function is called, it doesn’t return; therefore, we indicate using the never type.</p>
<p>You can not convert to never at all.</p>
<h3 id="heading-unknown">Unknown</h3>
<p>This special type tells TypeScript that we don’t know what the type of this variable is, but not to worry about it and that we will clarify it later. To maintain type safety, you should deduce the correct type before using an unknown variable.</p>
<h3 id="heading-any">Any</h3>
<div data-node-type="callout">
<div data-node-type="callout-emoji">⚠</div>
<div data-node-type="callout-text">Any <strong>SHOULD NOT</strong> be used in production code.</div>
</div>

<p>This is the last of the special types in TypeScript; all types can be converted to any, and all types can be converted to a narrower type from any. This makes it very dangerous, as you discard type checking completely when using any. There is no type-safe way to use the <code>any</code> type, the closest is to treat it like <code>unknown</code> But if you forget that TypeScript, it will not detect it, unlike with <code>unknown</code> where it will.</p>
<h1 id="heading-conversion">Conversion</h1>
<p>Now that we have a basic understanding of the type system, we can discuss how they get converted, sometimes called casting. TypeScript uses two strategies when converting: Type Narrowing, which goes down the type hierarchy tree from a broader type to a narrower one, and Type Broadening, which goes in the opposite direction, from a narrow type to a broader one.</p>
<h2 id="heading-cross-type-conversion">Cross-Type Conversion</h2>
<p>For completeness, cross-type conversion, going from one base type to another (i.e., from a string to a number), can not happen implicitly in TypeScript. You must always handle this explicitly using runtime functions such as <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt"><code>parseInt</code></a>.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">This can happen explicitly in TypeScript (i.e., without using runtime conversion), and you may find information on how to do it. However, this breaks type safety and should not get past a code review. I have intentionally chosen not to cover how to do it here.</div>
</div>

<h2 id="heading-broadening">Broadening</h2>
<p>This is the easiest to understand, and the easiest for TypeScript to do. This happens implicitly because it doesn’t require type checking.</p>
<p>When you broaden a type, you discard the extra type information and cast the type to the new broader type. Because it relies on discarding Information, you can not implicitly return to the narrower type once broadening occurs.</p>
<h2 id="heading-narrowing">Narrowing</h2>
<p>Because narrowing requires more information, TypeScript can rarely do this implicitly; the only time it can is when the value of a variable is guaranteed at compile time, which means if a variable is of one of these types. <code>string</code> , <code>number</code> , <code>boolean</code> <strong>AND</strong> declared with <code>const</code>. Objects are not included because of how they work under the hood. An object is considered <code>const</code> long as its underlying reference ID never changes, regardless of whether its shape changes. Due to this, even freezing using <code>Object.freeze</code> an object won’t guarantee that it won’t change at runtime. The exception to this is a const array, but you have to follow specific rules to declare them.</p>
<p>Because of this, you will most often need to help TypeScript understand how to narrow a type.</p>
<h2 id="heading-as">As</h2>
<p>When looking this up, you may come across the <code>as</code> keyword. The <code>as</code> A keyword allows you to instruct TypeScript that you know what is happening and want it to treat your broader type as the narrower type. This is not considered type safe because, as mentioned above, TypeScript only operates at compile time; therefore, it can only guarantee type safety at compile time. Using <code>as</code> it will result in possible runtime type mismatches being missed. The <code>as</code> keyword will also never allow you to change the type when no overlap exists. This is when the type you are converting to does not exist in the same inheritance chain; in that case, you are trying to cross-convert types.</p>
<h2 id="heading-type-assertion-functions">Type Assertion Functions</h2>
<p>This relatively new feature in TypeScript allows you to narrow the type and maintain type safety (when used correctly). Type Assertions bridge compile time and runtime, meaning they must be guaranteed at compile time. This allows TypeScript to use them when doing type narrowing. For them to be guaranteed at compile time, they must be declared with the <code>function name() {}</code> syntax not <code>const a = () =&gt; {}</code> or <code>const a = function() {}</code>. They must take at least one argument of the value you are checking, and should use the type <code>unknown</code>. They can take other arguments to help with asserting the type. They can not return a value and should only return if the variable matches the declared type. The type assertion function should throw if the variable does not meet the required type. This mimics the behaviour of assert in the Node standard library <code>node:assert</code> and other assertion libraries/languages. Due to the way they are defined, type assertion functions must be declared before use.</p>
<p>An example type assertion would look like</p>
<pre><code class="lang-typescript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">assertAType</span> (<span class="hljs-params">value: unknown</span>): <span class="hljs-title">asserts</span> <span class="hljs-title">value</span> <span class="hljs-title">is</span> &lt;<span class="hljs-title">TYPE</span>&gt; </span>{
}
</code></pre>
<p>The <code>asserts value is &lt;TYPE&gt;</code>is what makes this a type assertion, where <code>&lt;TYPE&gt;</code> is replaced with the type to which you want to assert the value conforms.</p>
<p>An example of this could be</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> assert <span class="hljs-keyword">from</span> <span class="hljs-string">"node:assert"</span>;
<span class="hljs-keyword">type</span> Px = <span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-built_in">number</span>}</span>px`</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">assertIsPx</span> (<span class="hljs-params">value: unknown</span>): <span class="hljs-title">asserts</span> <span class="hljs-title">value</span> <span class="hljs-title">is</span> <span class="hljs-title">Px</span> </span>{
  assert.equal(<span class="hljs-keyword">typeof</span> assert, <span class="hljs-string">"string"</span>, <span class="hljs-string">"Px should be a string"</span>);
  assert.ok(value.endsWith(<span class="hljs-string">'px'</span>), <span class="hljs-string">'should end in pixal'</span>);
  assert.ok(<span class="hljs-built_in">parseInt</span>(value, <span class="hljs-number">10</span>) !== <span class="hljs-built_in">Number</span>.NaN, <span class="hljs-string">"should contain a number"</span>);
}

<span class="hljs-keyword">let</span> width: <span class="hljs-built_in">string</span> = <span class="hljs-string">"10px"</span>; 
assertIsPx(width);
<span class="hljs-comment">// width type has now been narrowed from "string" to "Px"</span>
<span class="hljs-keyword">let</span> height: <span class="hljs-built_in">string</span> = <span class="hljs-string">"200"</span>;
assertIsPx(height);
<span class="hljs-comment">// this would throw an error because height doesn't confirm to the type rules </span>
<span class="hljs-keyword">let</span> depth: Px = <span class="hljs-string">"200px"</span>;
assertIsPx(depth);
<span class="hljs-comment">// This would pass and no type narrowing is needed so it will remain "Px"</span>
</code></pre>
<p>For type assertions to be valid, you must define the type rules in the assertion and ensure they cover everything the new type must have. This can be complex; the more complicated the type is, the simpler the assertion is. The above example is simple, and so is its assertion. This is because the following is valid, but pointless as it doesn’t do any type checking; however, if used like the assertion function above, it will mean any variable passed to value will become of type. <code>Px</code> As far as TypeScript is concerned, it doesn’t match the type rules.</p>
<pre><code class="lang-typescript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">assertIs</span> (<span class="hljs-params">value: unknown</span>): <span class="hljs-title">asserts</span> <span class="hljs-title">value</span> <span class="hljs-title">is</span> <span class="hljs-title">Px</span> </span>{}
</code></pre>
<h1 id="heading-fun-fact">Fun Fact</h1>
<p>If you are wondering why you have to use <code>function name() {}</code> over <code>const name = () =&gt; {}</code> or <code>const name = function () {}</code></p>
<p>This is because of the need to be guaranteed at compile time. <code>function name() {}</code> Declares a function; this function exists as soon as the runtime engine starts, and remains immutable until the runtime engine completes and exits.</p>
<p>On the other hand <code>const name = () =&gt; {}</code> and <code>const name = function () {}</code> Assign a reference to a function. This means that <code>const name</code> becomes type <code>Function</code> which in turn is a child type of <code>object</code> , as long as the object reference ID stored in <code>const name</code> doesn’t change it, doesn’t violate the immutability of <code>const</code> The result is that the name value can’t be guaranteed at compile time, so TypeScript can’t use it.</p>
<div class="hn-embed-widget" id="cc-license"></div>]]></content:encoded></item><item><title><![CDATA[My Typescript Stack in 2025]]></title><description><![CDATA[💡
TL;DR: See my Typescript GitHub template, the Readme includes how to get started


If you have read any of my other posts, you are likely aware that my primary coding stack is based on TypeScript. Working in modern JavaScript can be complex; a mod...]]></description><link>https://articles.dotmh.dev/my-typescript-stack-in-2025</link><guid isPermaLink="true">https://articles.dotmh.dev/my-typescript-stack-in-2025</guid><category><![CDATA[secretlint]]></category><category><![CDATA[stack]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[nvm]]></category><category><![CDATA[pnpm]]></category><category><![CDATA[eslint]]></category><category><![CDATA[Prettier]]></category><category><![CDATA[conventional commits]]></category><category><![CDATA[commitlint]]></category><category><![CDATA[vitest]]></category><category><![CDATA[istanbul]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[github-actions]]></category><category><![CDATA[devcontainers]]></category><dc:creator><![CDATA[Martin Haynes]]></dc:creator><pubDate>Wed, 07 May 2025 23:00:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/Y376h7VN27c/upload/69ffe6f3b73d8b0e839775ce812fa8e0.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">TL;DR: See my Typescript <a target="_self" href="https://github.com/dotmh/ts">GitHub template</a>, the <a target="_self" href="https://github.com/dotmh/ts/blob/main/README.md">Readme</a> includes how to get started</div>
</div>

<p>If you have read any of my other posts, you are likely aware that my primary coding stack is based on TypeScript. Working in modern JavaScript can be complex; a modern JavaScript project often involves numerous moving parts to be productive and comfortable. Setting up these moving parts can be a time-consuming process. I tend to create numerous projects, whether a library, a whole project, or an experiment; I want all my standard tooling. I therefore decided to make a <a target="_blank" href="https://github.com/dotmh/ts">GitHub template</a> repository that I can use to generate new repositories when I want to work with TypeScript.</p>
<p>This post will walk through the template's stack and explain the rationale behind choosing each part. This doesn’t mean you have to use this technology, but for me, these are the best technologies currently available in 2025. The <a target="_blank" href="https://github.com/dotmh/ts/blob/main/README.md">Readme</a> covers the setup and other helpful information if you want to use the template.</p>
<p>We recently adopted this stack at work, which means it is also used professionally.</p>
<h2 id="heading-node">Node</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746026088273/6b9a071f-2a3c-4094-9bd3-5547bfa6749c.png" alt class="image--center mx-auto" /></p>
<p>To manage nodes, I use <a target="_blank" href="https://github.com/nvm-sh/nvm">NVM.</a> I have used it for a long time and am comfortable using it. I also like that you can switch node versions when entering a node project by detecting the <code>nvmrc</code> file. It is also well-supported by other tooling and <a target="_blank" href="https://code.visualstudio.com/">VSCode,</a> my primary IDE.</p>
<h2 id="heading-package-manager">Package Manager</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746025836923/efedee8f-5dd3-43ea-941b-a0b07ba30cea.png" alt class="image--center mx-auto" /></p>
<p>Nowadays, I almost exclusively use <a target="_blank" href="https://pnpm.io/">PNPM</a> to manage my dependencies in Node projects. There are two main reasons for that.</p>
<p>The first is that PNPM provides excellent tooling for managing a monorepo through its workspace tooling. You can easily link packages under the repo, build and package code for deployment and scope commands to a package within a workspace.</p>
<p>The other significant benefit of PNPM is that it reduces the space required for your packages on a disk. We have all, by now, seen the meme of <code>node_modules</code> Having a density greater than that of a black hole, being able to reduce it is a massive benefit.</p>
<p>You can read more about the motivation behind PNPM and how it reduces install sizes on the <a target="_blank" href="https://pnpm.io/motivation">PNPM Website</a>.</p>
<h2 id="heading-typescript">Typescript</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746025911937/467f89b1-a9b3-4602-b6c6-3ac8c758eea0.png" alt class="image--center mx-auto" /></p>
<p>It shouldn’t come as a shock now, but the central part of my stack is <a target="_blank" href="https://www.typescriptlang.org/">Typescript</a>. I use TypeScript because it makes JavaScript easier and safer to use. For anyone who hasn’t encountered TypeScript yet, it is essentially a superset of JavaScript, meaning that all valid JavaScript is also valid TypeScript. However, TypeScript supports type annotations. This adds safety to working with JavaScript, reducing bugs and edge cases. It also reduces the number of tests you write, as the TypeScript compiler can do the work.</p>
<p>Like many influential and essential tools, Typescript requires a commitment to learn how to use it effectively and maximise its benefits. However, it makes a big difference in building reliable and robust codebases that run anywhere JavaScript can.</p>
<h2 id="heading-linting">Linting</h2>
<h3 id="heading-eslint">ESLint</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746110925678/18979ba3-cb45-40d9-942a-7b3a23d7dc62.png" alt class="image--center mx-auto" /></p>
<p>I use ESLint partly out of habit but primarily because it allows me the most flexibility when defining the code style I want. Although opinionated, pre-configured tooling is available to enforce a set of sensible defaults, I prefer to manage code style rules myself.</p>
<p>I bundled a shared configuration under the GitHub repository <a target="_blank" href="https://github.com/dotmh/shared-typescript-configuration"><strong>shared-typescript-configuration</strong></a><strong>,</strong> which allows me to share my ESLint settings across projects. I then distribute these settings as an <a target="_blank" href="https://www.npmjs.com/package/@dotmh/eslint-config-ts">NPM module</a>, which I can consume in the project. This is also how the template is set up, and it creates its own <code>eslint.config.mjs</code> in the root, exports the config from the node module.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> base <span class="hljs-keyword">from</span> <span class="hljs-string">'@dotmh/eslint-config-ts'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> [
  ...base,
  {
    <span class="hljs-attr">ignores</span>: [<span class="hljs-string">'dist/'</span>, <span class="hljs-string">'/coverage'</span>, <span class="hljs-string">'node_modules/'</span>, <span class="hljs-string">'**/*.js'</span>, <span class="hljs-string">'**/*.mjs'</span>],
  },
];
</code></pre>
<h3 id="heading-prettier">Prettier</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746111011779/9458fbcb-d3f9-4f3f-8c2d-b0c2784cab02.png" alt class="image--center mx-auto" /></p>
<p>Whereas ESLint primarily targets code smells and enforces good practices, Prettier enforces the actual physical style of the code, including aspects such as which quotes to use. I prefer Prettier for many of the same reasons I prefer ESLint; it allows me to control my code style. Both tools require a little time to set up and tune to your liking, but once done, they’re set.</p>
<p>Again, like with ESLint, I bundle my settings into an <a target="_blank" href="https://www.npmjs.com/package/@dotmh/prettier-config">NPM module</a> whose source comes from the same <a target="_blank" href="https://github.com/dotmh/shared-typescript-configuration">shared-typescript-configuration</a> repository on GitHub.</p>
<h3 id="heading-secret-lint">Secret Lint</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746111428533/64004514-22bb-4a3b-a8a1-ddf082417baf.png" alt class="image--center mx-auto" /></p>
<p>Secret Lint scans code for secrets and a <a target="_blank" href="https://typicode.github.io/husky/">Husky</a> hook that triggers when anyone attempts to commit, thereby reducing the risk that a Secret will be included in the repository. Due to the way GitHub operates to facilitate collaboration, it is complicated to remove something once it is added to a repository. Secret scanning tools that work at the CI level or as a GitHub app are great, but they don’t prevent a secret from being introduced in the first place. This lack of prevention means that once these tools detect a secret being committed, you must rotate all your secrets, which is not a small amount of work.</p>
<h3 id="heading-commit-lint">Commit Lint</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746116098888/ab26f007-4c9a-49c1-8857-8bafdbf8fa22.png" alt class="image--center mx-auto" /></p>
<p>Commit lint instead of linting code; it lints the commit messages. I have it set up to enforce <a target="_blank" href="https://www.conventionalcommits.org/en/v1.0.0/">conventional commits</a>. I prefer conventional commits because they provide a structure for writing clear and concise commit messages. I am terrible at writing commit messages, let alone meaningful commit messages, but with conventional commit messages as a guide, the situation is greatly improved. I also know myself and if nothing is enforcing me to use conventional commits I will end, when I am rushed, tired or excited falling back to my typical bullshit, hence the need for a linter.</p>
<h2 id="heading-testing">Testing</h2>
<h3 id="heading-vitest">Vitest</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746518664312/6b82cede-b095-437c-ad12-829e18ed83a3.png" alt class="image--center mx-auto" /></p>
<p>I was recently introduced to vitest by a friend and colleague as an alternative to <a target="_blank" href="https://jestjs.io/">Jest</a>. It labels itself as a fast, Jest-compatible testing framework that integrates with <a target="_blank" href="https://vite.dev/">Vite</a>. This seemed ideal for me; until recently, Jest was my preferred testing framework, Vite is my preferred build tool, and it had native support for both TypeScript and code coverage reporting with Istanbul. Vitest also had good support for working within a monorepo, which I extensively utilise (although Jest may have had that support too, I never looked into it). The template mentioned in the article is set up as a monorepo. I used Vitest on a number of both backend and frontend projects, and found it easy to use, integrate and have a nice set of functions and keywords; I like the “describe”, “it” and “expect” way of writing tests.</p>
<h3 id="heading-istanbul">Istanbul</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746518681306/b7e13e7e-33f8-4c41-97d0-9cf32999d3d9.png" alt class="image--center mx-auto" /></p>
<p>Code coverage seems to have a lot of baggage in the developer world. I like it, as it is a valuable guide to making sure that I am writing code tests covering the functionality. I don’t think it is a metric that should have much enforcement. It should be a guide. There are several downsides to relying on code coverage because, like all metrics, it can lead to a false sense of security and wasted effort without understanding what it tells you. I use Istanbul out of habit; its HTML report is easy to use and read.</p>
<h2 id="heading-github-actions">GitHub Actions</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746518702992/e78badc2-e232-42ff-a36a-cede2b60660f.png" alt class="image--center mx-auto" /></p>
<p>Continuous integration and continuous deployment are potent tools for software development. Although there has been some interesting <a target="_blank" href="https://world.hey.com/dhh/we-re-moving-continuous-integration-back-to-developer-machines-3ac6c611">discussion</a> lately about whether it is worth using a service, it is still considered valid and a requirement by many organisations. I have used many CI systems, including JetBrains <a target="_blank" href="https://www.jetbrains.com/teamcity/">TeamCity</a>, <a target="_blank" href="https://semaphore.io/">Semaphore</a> and <a target="_blank" href="https://circleci.com/">Circle CI</a>. However, my favourite CI platform was <a target="_blank" href="https://docs.gitlab.com/ci/">GitLab CI</a>. Its ease of use and deep integration with the code repositories made it pleasant to work with.</p>
<p>For several reasons, though, I am now mostly using GitHub, so when they launched GitHub Actions, I was interested in what it offered. GitHub Actions is more than just a plain CI/CD tool; it is an event-based system that can trigger actions based on a load of events in GitHub. This allows you to build powerful workflows using it. GitHub Actions has an ecosystem; you can use first- and third-party actions in your workflows. This allows for rapid workflow development, though it exposes you to supply chain attacks like any package-based ecosystem.</p>
<p>I chose to use GitHub Actions in my template for these reasons. This means users don’t have to sign up for third-party services. If they are using the GitHub template, then they are already on GitHub.</p>
<h2 id="heading-dev-containers-and-github-codespace">Dev Containers and GitHub Codespace</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746549071410/8a465a87-9e58-4662-b514-8e50fc8b5a82.png" alt class="image--center mx-auto" /></p>
<p>Docker changed the development world. With a single command, you can have a reproducible, lightweight runtime environment that matches production to run your app. Imagine having that for your development environment. Well, that is Dev Containers. Dev Containers integrate with <a target="_blank" href="https://code.visualstudio.com/">VS Code</a> and most <a target="_blank" href="https://www.jetbrains.com/ides/">JetBrains IDES</a>, allowing you to work seamlessly within the dev container as if it were your file system while having all the tools you need in an environment close to your production environment.</p>
<p>I also like Dev Containers because I love to explore other languages and tools. They allow me to test and play with those without the overhead of installing them into my main machine. This benefits from testing in a virtual machine, but with the lightweight overhead of containers.</p>
<p>Github Codespaces builds on top of Dev Containers, allowing you to run a dev environment in the cloud that you can either attach to through a browser with VS Code, or directly in the VS Code app or JetBrains IDE through <a target="_blank" href="https://www.jetbrains.com/remote-development/gateway/">JetBrains Gateway</a>. This is great if you want to work on a project without downloading it or using someone else’s or an underpowered machine. Codespaces cost money and aren’t the end-all solution for daily development, but can be really useful in certain situations.</p>
<p>I want to write a full post on dev containers soon, but if you wanna learn more, I have a <a target="_blank" href="https://github.com/dotmh/devcontainer">repository</a> that contains several dev containers that are also deployed as <a target="_blank" href="https://github.com/dotmh?tab=packages&amp;repo_name=devcontainer">packages</a> in GitHub, ready for use.</p>
<div class="hn-embed-widget" id="cc-license"></div>]]></content:encoded></item><item><title><![CDATA[My Development Heroes]]></title><description><![CDATA[If you are passionate about something, whether it be music, film, video games, gardening, technology, or another interest, then you will likely have heroes—people who inspire you, who drive your passion and who influence you. I have many passions, bu...]]></description><link>https://articles.dotmh.dev/my-development-heroes</link><guid isPermaLink="true">https://articles.dotmh.dev/my-development-heroes</guid><category><![CDATA[development]]></category><category><![CDATA[Heroes]]></category><category><![CDATA[programming]]></category><category><![CDATA[software development]]></category><dc:creator><![CDATA[Martin Haynes]]></dc:creator><pubDate>Wed, 30 Apr 2025 23:00:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/zEawlLdVloo/upload/6aa0400d79ef73f82eaa85e634322e13.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you are passionate about something, whether it be music, film, video games, gardening, technology, or another interest, then you will likely have heroes—people who inspire you, who drive your passion and who influence you. I have many passions, but these articles primarily focus on software development. I thought I would talk about the people who inspire me. I want to say at the outset that these are individuals who have inspired me; however, people are unique and have their own distinct sets of strengths and weaknesses. I am in no way suggesting that these people are perfect, nor am I inspired by everything they do. I just wanted to highlight people who, in some way, have inspired me. This list is also unordered.</p>
<h2 id="heading-bill-gates">Bill Gates</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745921975622/d01a376b-1cf2-4b7c-9dfa-f7dcc448de38.jpeg" alt class="image--center mx-auto" /></p>
<p>I was conflicted about including Bill Gates. I think that Bill Gates has made both positive and negative contributions to the tech world. I do look up to Bill Gates while still accepting that he has made some damaging decisions in the past. The main reason I have him on my list is that his work at the beginning of the microcomputer revolution sparked my excitement and interest in technology. He wrote and ported Microsoft BASIC to a vast majority of early Microcomputers, such as the C64 and Amstrad. He was also an essential part of inventing the PC platform, with Microsoft DOS, and arguably helped promote the PC platform through further refinements to DOS and then Windows. Bill Gates also oversaw the release of the XBOX brand, Directx, and .net, which have been significant influences on me.</p>
<p>Read more on <a target="_blank" href="https://en.wikipedia.org/wiki/Bill_Gates">Wikipedia</a>.</p>
<h2 id="heading-john-carmack">John Carmack</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745923830238/b1e67fe1-360d-4ba6-af82-7c2021b30c08.jpeg" alt class="image--center mx-auto" /></p>
<p>John Carmack is a much less divisive person to put on this list. In the early 90s, John Carmack was a massive contributor to the world of computer graphics, and more specifically, 3d graphics. John Carmack led innovations with <a target="_blank" href="https://en.wikipedia.org/wiki/Commander_Keen">Commander Keen</a> that brought smooth scrolling to the PC, including <a target="_blank" href="https://en.wikipedia.org/wiki/Wolfenstein_3D">Wolfenstein 3d</a>, a pioneer in 3d graphics. <a target="_blank" href="https://en.wikipedia.org/wiki/Doom_\(1993_video_game\)">Doom</a> raised the bar again and significantly advanced the first-person shooter genre in popular culture. Then, <a target="_blank" href="https://en.wikipedia.org/wiki/Quake_\(video_game\)">Quake</a> brought lightning to the computer graphics world, making 3d games look increasingly amazing. These are all fantastic things, but for me, however, it was Doom and Doom map editing that grew my interest in computing. The fact that he and the others at ID decided to open-source the game engine has not only contributed to my learning but also to the software industry as a whole.</p>
<p>If you want to learn more about John Carmack and the development of some of these seminal games, I recommend the book <a target="_blank" href="https://amzn.eu/d/eorIeCQ">"Masters of Doom"</a> <a target="_blank" href="https://amzn.eu/d/eorIeCQ">by David Kushner</a>.</p>
<p>Read more on <a target="_blank" href="https://en.wikipedia.org/wiki/John_Carmack">Wikipedia</a>.</p>
<h2 id="heading-steve-wozniak">Steve Wozniak</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745934476925/ab3af082-ab44-48ae-8fb4-aefce5ea1828.jpeg" alt class="image--center mx-auto" /></p>
<p>Born in the 1950s and present at the dawn of the computing era, Steve Wozniak was a pivotal figure in the early days of the computing industry. If <a target="_blank" href="https://en.wikipedia.org/wiki/Steve_Jobs">Steve Jobs</a> was the person who sold the personal computer to the world, then it was Steve Wozniak who designed that computer. At the birth of the microcomputer in the US, there was a trinity of pioneering micros: the <a target="_blank" href="https://en.wikipedia.org/wiki/TRS-80">TRS-80</a>, the <a target="_blank" href="https://en.wikipedia.org/wiki/Commodore_PET">Commodore PET</a>, and, of course, Apple’s <a target="_blank" href="https://en.wikipedia.org/wiki/Apple_II_\(original\)">Apple II</a>, designed by Woz. I believe it's challenging to overstate Steve Wozniak's contributions to our modern technological world. The Apple II didn’t just revolutionise the computer; it went on to inspire millions of people to contribute to the field. Steve Wozniak went on to co-develop the Macintosh, another groundbreaking computer in its own right, which allowed Apple to continue innovating and popularising new technologies like the iPod, smartphone, and tablet. I think that I can safely say that Steve Wozniak is one of the giants whose shoulders I stand on today as a software developer.</p>
<p>Read more on <a target="_blank" href="https://en.wikipedia.org/wiki/Steve_Wozniak">Wikipedia</a>.</p>
<h2 id="heading-anders-hejlsberg">Anders Hejlsberg</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745937607763/6c71c3f0-be33-4ee7-8f3a-7504bcca624a.jpeg" alt class="image--center mx-auto" /></p>
<p>Unlike the others on the list, you may not be familiar with Anders Hejlsberg, but to me, he is one of the most significant individuals on this list. In my recent blog post, “<a target="_blank" href="https://articles.dotmh.dev/returning-to-windows">Returning to Windows</a>,” I mentioned Anders Hejlsberg, which may be the first time you've heard of him. I attended college in the early 2000s to study computer science, and during that time, two of the programming languages we used were <a target="_blank" href="https://en.wikipedia.org/wiki/Turbo_Pascal">Borland Turbo Pascal</a> and <a target="_blank" href="https://en.wikipedia.org/wiki/Delphi_\(software\)">Borland Delphi</a>. Delphi is to Pascal what Visual Basic is to BASIC. These were the languages and technologies that I enjoyed and wanted to explore further; these are what kick-started my life as a software developer. Anders Hejlsberg was the lead creator of both. If it were only for that alone, Anders Hejlsberg would be a hero to me. However, later in my career, I started writing in Typescript. I adopted it as a language to write in early on and have been writing almost exclusively in <a target="_blank" href="https://en.wikipedia.org/wiki/TypeScript">TypeScript</a> since 2021. This year, 2025, I started learning the .net Framework through <a target="_blank" href="https://en.wikipedia.org/wiki/C_Sharp_\(programming_language\)">C#</a>, and as you may have guessed by now, Anders Hejlsberg was the lead architect for both.</p>
<p>Read more on <a target="_blank" href="https://en.wikipedia.org/wiki/Anders_Hejlsberg">Wikipedia</a>.</p>
<h2 id="heading-yukihiro-matsumoto">Yukihiro Matsumoto</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745942848318/b0fec8b9-7c51-48da-ba9a-6cff19633238.jpeg" alt class="image--center mx-auto" /></p>
<p>I have a habit of learning a new Language. When I am comfortable with my primary language, I try to learn something new. This provides me with insights into new ways of doing things and new ideas, as well as access to a new language and its associated tooling and ecosystem. The first language that I ever learnt, once I was comfortable with the web stack I was using (PHP, JavaScript, HTML, etc), was <a target="_blank" href="https://en.wikipedia.org/wiki/Ruby_\(programming_language\)">Ruby</a>. Ruby showed me a whole new world. It was very object-oriented, which gave me a much better insight into that way of working, and it was the first language for me that wasn’t inspired by the <a target="_blank" href="https://en.wikipedia.org/wiki/C_syntax">C syntax</a>. I went on an adventure, and for a few years, I pivoted my career to working with the Ruby programming language; I have recently put that knowledge to use again. I believe the practice of learning new languages is essential for building a more well-rounded development career, as it teaches you ways to solve different problems, introduces new tools, and, of course, provides a new skill that you can apply.</p>
<p>Read more on <a target="_blank" href="https://en.wikipedia.org/wiki/Yukihiro_Matsumoto">Wikipedia</a>.</p>
<h2 id="heading-ryan-dahl">Ryan Dahl</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746004167378/f6ab77f3-7136-4e74-8c7e-9d7efb3053dc.jpeg" alt class="image--center mx-auto" /></p>
<p>Ryan Dahl was the person who made JavaScript popular everywhere and was the creator behind <a target="_blank" href="https://nodejs.org/en">Node.js</a>. He may have <a target="_blank" href="https://www.youtube.com/watch?v=M3BM9TB-8yA">regretted</a> it, but it changed modern web development and, by extension, modern software development. Before Node was invented, JavaScript was pretty much confined to the frontend and the browser. After Node, it has all changed, and now you can use Node everywhere. Electron allows you to create desktop applications, while React Native and Ionic enable you to build mobile applications. JavaScript is now a scripting language in other tools, like a game engine. I have mentioned before that I use TypeScript daily and have utilised it in all these contexts. I can’t underestimate the influence Ryan Dahl has had on my career and daily life.</p>
<p>Read more on <a target="_blank" href="https://en.wikipedia.org/wiki/Ryan_Dahl">Wikipedia</a>.</p>
<h2 id="heading-linus-torvalds">Linus Torvalds</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746007157630/887e87de-da91-486c-8983-a6e1da0705c5.jpeg" alt class="image--center mx-auto" /></p>
<p>I am not sure if I need to tell you who Linus Torvalds is; he is the man who made Linux, and to this day, he is the lead developer and architect. The impact that Linux has had on the programming and computer worlds is immense. Apart from Desktop and Laptop computing, it would not be an exaggeration to say that Linux powers the world. Yes, other operating systems exist and do work in many fields, but Linux dominates. Linux powers the servers on which I deploy my code every day, the servers that run my services, the dishwasher that washes my dishes, the smart TV on which I watch my entertainment, and half of the devices on which I play my games. Linux changes the world by providing a well-made, secure, Unix-like, and, most importantly, free operating system.</p>
<p>Read more on <a target="_blank" href="https://en.wikipedia.org/wiki/Linus_Torvalds">Wikipedia</a>.</p>
<h2 id="heading-tim-berners-lee">Tim Berners-Lee</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746008897343/850827b1-e4ed-451f-ab0a-5635a4ed2512.jpeg" alt class="image--center mx-auto" /></p>
<p>Another person whom I am not sure I need to introduce. The modern world's most powerful tool and arguably most important invention was, in a large part, the idea of Tim Berners-Lee. I have mentioned how others inspired me to code; it was the World Wide Web, where I started. I started by building my own web pages to allow me to share my game maps. I started with just plain HTML, and as I gradually added more functionality over time, I learned additional languages, including JavaScript, CSS, PHP, SQL, and eventually. NET. If it wasn’t for Tim Berners-Lee and his idea, I am certain I wouldn’t be where I am today. There was something magical about contributing to this fantastic invention. In 2025, we live in two worlds: one physical and one of information, and Tim Berners-Lee invented the language and technology that underpin that world. Yes, many have added to it over the years, but Tim was the catalyst that brought it into existence.</p>
<p>Read more on <a target="_blank" href="https://en.wikipedia.org/wiki/Tim_Berners-Lee">Wikipedia</a>.</p>
<h2 id="heading-honourable-mentions">Honourable Mentions</h2>
<p>All these individuals have had an impact on my career development and enhanced my skills in one way or another.</p>
<p>All these are LinkedIn links.</p>
<ul>
<li><p><a target="_blank" href="https://www.linkedin.com/in/dylanbeattie/">Dylan Beattie</a> - A Speaker and Developer who opened my eyes to so many interesting topics.</p>
</li>
<li><p><a target="_blank" href="https://www.linkedin.com/in/kevlin/">Kevlin Henney</a> - Another Speaker who has made me think about how to be a better developer</p>
</li>
<li><p><a target="_blank" href="https://www.linkedin.com/in/william-munn-98590a14/">William Munn</a> - An Amazing developer, mentor and lead who drove me to write better code</p>
</li>
<li><p><a target="_blank" href="https://www.linkedin.com/in/markbold1/">Mark Bold</a> - My first lead after I became a professional developer, who taught me how to be a professional</p>
</li>
</ul>
<h2 id="heading-standing-on-the-shoulders-of-giants">Standing On The Shoulders Of Giants</h2>
<p>The people listed above are the giants I stand on the shoulders of, but they are just the top level of giants. Under these people are other giants that they are standing on, and under them are more giants that they are standing on. This giant among giants goes back in time to the dawn of humanity. These giants also come from all walks of life, genders and races. Just because I have chosen these people to highlight in my personal story doesn’t mean that I disregard the contributions that came before them.</p>
<div class="hn-embed-widget" id="cc-license"></div>]]></content:encoded></item><item><title><![CDATA[Returning to Windows]]></title><description><![CDATA[Born in the early 1980s, I grew up during the same period when the microprocessor was experiencing an unprecedented surge. Before the 1970s, a computer was a room-sized machine, consisting of multiple cabinets filled with electronics; it wasn’t somet...]]></description><link>https://articles.dotmh.dev/returning-to-windows</link><guid isPermaLink="true">https://articles.dotmh.dev/returning-to-windows</guid><category><![CDATA[Windows]]></category><category><![CDATA[macOS]]></category><category><![CDATA[Developer Tools]]></category><dc:creator><![CDATA[Martin Haynes]]></dc:creator><pubDate>Wed, 23 Apr 2025 23:00:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/AigsWJmvoEo/upload/7e3ea4a08ea495ac503e3ceb928d5125.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Born in the early 1980s, I grew up during the same period when the microprocessor was experiencing an unprecedented surge. Before the 1970s, a computer was a room-sized machine, consisting of multiple cabinets filled with electronics; it wasn’t something that could be easily had at home. This all changed in 1971 with the introduction of the <a target="_blank" href="https://en.wikipedia.org/wiki/Intel_4004">Intel 4004</a>; now it was a <a target="_blank" href="https://en.wikipedia.org/wiki/Altair_8800">box</a> that could sit on a desk. By the time the 1980s rolled around, the microprocessor had become the new hotness, with hundreds of machines being launched that incorporated this new technology.</p>
<p>The first machines that I used were these primitive computers, with my first real experience being on a <a target="_blank" href="https://en.wikipedia.org/wiki/BBC_Micro">BBC Micro from Acorn</a>. I am from the UK, and the Beeb, as it was affectionately known, was the de facto school computer, in no small part because it was sponsored by the British Broadcasting Corporation's Computer Literacy program. I also used other micros of the time, including the Commodore 64 and the Spectrum, as well as early incarnations of the IBM PC.</p>
<p>Due to the high cost of computer ownership, even though microcomputers had driven the price down, it was still a significant expenditure; a family would tend to have only one, which was shared, and we were much the same. We acquired an IBM-compatible PC relatively early, but it was a 386, and from then on, we had a PC. This meant that I grew up using the Microsoft family of operating systems, starting with MS-DOS and moving through Windows 3.11, 95, 98, NT 4.0, Me, 2000, and eventually XP.</p>
<p>However, in 2006, when deciding on my next upgrade, I began to consider a Mac. My interaction with the Apple world had been limited up until that point, as mentioned, in the UK, Apple wasn’t the default in schools, and at home, I was using a PC. I had used a Mac for one term in college, but that was about it. The thing was, I am a music lover, and during this time, a massive shift was happening in the music industry. Music was going digital, and the Apple iPod was leading the way. A few years earlier, I had joined the revolution, getting a fourth-generation iPod. This means Apple was now on my radar. My computing needs at this time weren’t complex. I was dabbling in coding, making music, and surfing the internet - all things I could continue to do on the Mac. In 2006, I purchased a white MacBook.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745072130744/1d40498e-2a04-4e44-84c9-3edff9e31d82.jpeg" alt class="image--center mx-auto" /></p>
<p>This started a 19-year love affair with the Mac platform. One of the most significant contributors to this was the recent career change. I had been building software as a hobbyist since my early teens, but in 2008, I took that passion and transitioned to working full-time as a professional Web Developer. My early career involved working with the LAMP (Linux, Apache, Mysql, and PHP) stack, which meant that OS X was an ideal platform for professional web development.</p>
<p>To understand why the Mac was well-suited for web development, it's helpful to have a little background on operating systems. By 2008, there were essentially two major families of operating systems used in desktop and laptop computing. These were Windows and Nix (a catch-all term for Unix and Linux). MacOS (as of version 10) falls into the Nix family, being based on Apple’s XNU Unix kernel, which incorporates large parts of the Freebsd kernel. As many open-source projects target the Linux ecosystem, and Unix been a close cousin of Linux, this means that much of this tooling also works on Macos. This close compatibility between Linux and Unix also means that my development environment closely matches the production environment, which, of course, is the LAMP stack, which is Linux. However, unlike Linux, MacOs was a commercially supported operating system, which meant that you had access to a lot of commercial software packages, such as the Adobe suite. These tools were heavily utilised in the world of web development, particularly in the mid-2000s, before the emergence of Sketch and Figma.</p>
<p>From 2006 onwards, I invested in the Mac Ecosystem, purchasing several MacBook Pros and also acquiring the iPhone and Apple TV. I was an Apple fanboy, often defending the ecosystem, and recommended it to others where it made sense. In 2025, it became clear that my 2019 MacBook Pro was nearing the end of its useful life as a primary machine, and it was time to update. Initially I was in two minds about which Mac to replace it with, I didn’t tend to use it as a laptop, most of the time it stayed docked to my desk, that along with the fact it suffered from over heating in summer meant that my thinking was between another MacBook Pro or a Mac Studio.</p>
<p>I visited the Apple website to configure a Mac Studio and a MacBook Pro. I always acknowledged that you pay a premium for Mac hardware. I was okay with that because I felt I was getting a premium product. This time, however, it was different. The multipliers of the cost of just getting a decent amount of RAM and storage seem so overpriced. This prompted me to explore alternatives, such as Linux or possibly Windows. If I could switch to standard hardware, it would reduce the cost and make it easier to customise my experience to best fit my needs, and it wouldn’t cost body parts to obtain.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745072838308/1bcd85f3-db22-47e8-b024-d40447e4e50f.jpeg" alt class="image--center mx-auto" /></p>
<p>This wouldn’t have even been a consideration back in 2008, but the world has undergone significant changes in the last 17 years. You don’t need your development machine to match production; Docker runs everywhere; you can spin up a Docker container and get the exact same environment that you are using in production. The most significant design tool in modern web and UI design is Figma, a browser-based tool that natively supports Windows, allowing it to run on almost any platform.</p>
<p>So, I'm not going to beat around the bush; you know from the title that I went with Windows, and more specifically, a <a target="_blank" href="https://valid.x86.fr/gbdmrs">custom-built</a> PC running Windows 11 Pro. So, why Windows? Well, Windows and Microsoft are very different beasts from what they were in the past. Microsoft has invested heavily in being more open-source, with tooling such as Visual Studio Code being open-source and languages like TypeScript, as well as their primary .net platform, all being open-sourced. Windows also now features the Windows Subsystem for Linux (WSL), which allows you to interact with your computer for the most part as if it were running Linux. When that isn’t possible, PowerShell presents a much more powerful command-line interface than the old DOS prompt, with aliases for standard Linux commands. You can even install some of the tools I use every day in PowerShell, such as <a target="_blank" href="https://github.com/eza-community/eza">EZA</a> and <a target="_blank" href="https://github.com/sharkdp/bat">BAT</a>. Windows can also run games, pretty much any PC game in the universe can run on Windows, whether you like it or not, Windows is the de facto standard when it comes to PC games.</p>
<p>There was also another reason that I decided to go with Windows, since about 2015, I have been a full-time JavaScript developer. Since about 2018, this has meant primarily writing TypeScript. I love working with TypeScript so much that I even created a <a target="_blank" href="https://github.com/dotmh/ts">template</a> for building new TypeScript projects. I use TypeScript almost exclusively, both at work and on my side projects. Every so often, though, typically when I am pretty advanced in a language, I like to learn a new one; this keeps life interesting and also shows me new ways of doing things, new ideas, and patterns that I can apply to my primary language. This year, I started learning C#. I chose C# because it is a general-purpose language that can be used to develop a wide range of software. It was also designed by <a target="_blank" href="https://en.wikipedia.org/wiki/Anders_Hejlsberg">Anders Hejlsberg</a>, the primary designer and developer of TypeScript.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💬</div>
<div data-node-type="callout-text"><em>Side note, Anders has had a significant influence on my programming career, even more than I initially realised. Not only did he design TypeScript, which I use every day, but he also created C#, which I am learning now. Additionally, he designed the two languages I enjoyed working with most in college, Turbo Pascal and Delphi, which kick-started my passion for software development.</em></div>
</div>

<p>The final reason for going with Windows was for Music production. I create music as a hobby, mostly using software these days, and my key tool in this is Steinberg <a target="_blank" href="https://www.steinberg.net/cubase/">Cubase</a>. I know some alternatives run on Linux-based operating systems, but this is just a hobby, and I am not interested in learning new software so that I don’t have to use Windows. I have also invested in Cubase, as well as instruments, effects, and other plugins that work with it.</p>
<p>The great thing about custom-building my machine is that I can decide what I put on it. If I wanna try Linux, then that is possible. Gaming on Linux is continually improving. Steam and the Steam Deck have made Linux a pretty good platform for gaming. I may try daily driving Linux in the future, though I opted for an Nvidia video card, which may make it harder to do so. For now, I am a happy Windows user.</p>
<div class="hn-embed-widget" id="cc-license"></div>]]></content:encoded></item><item><title><![CDATA[The Great AI Fad]]></title><description><![CDATA[Unless you have been living under a rock recently, you can’t help but have seen the near-hysterical excitement surrounding AI in the tech industry. Although the technology behind this craze has been around for several years under the banner of machin...]]></description><link>https://articles.dotmh.dev/the-great-ai-fad</link><guid isPermaLink="true">https://articles.dotmh.dev/the-great-ai-fad</guid><category><![CDATA[technology]]></category><category><![CDATA[AI]]></category><category><![CDATA[thoughts]]></category><dc:creator><![CDATA[Martin Haynes]]></dc:creator><pubDate>Thu, 17 Apr 2025 14:18:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/ac6UGoeSUSE/upload/25f96c93985e08a428387baf091ff67b.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Unless you have been living under a rock recently, you can’t help but have seen the near-hysterical excitement surrounding AI in the tech industry. Although the technology behind this craze has been around for several years under the banner of machine learning, the popularisation of the large language model by Open AI Chat GPT sparked this new wave of excitement and hype.</p>
<p>I have been interested in the tech sector for over 30 years, since I was a child and have worked full-time in it for about 17 years. I have witnessed many trends emerge and fade, from the widespread adoption of the web through the rise of the smartphone and Web 2.0 to the crypto boom and the advent of voice assistants, but apart from perhaps the <a target="_blank" href="https://en.wikipedia.org/wiki/Dot-com_bubble">dot-com bubble</a>, I haven’t seen anything on the same scale as AI.</p>
<p>Over the last few years, every major and minor tech company has attempted to incorporate AI into its products and offerings, regardless of whether it makes sense or not. I don’t think there is a service you can sign up for that doesn’t feature AI as a key component. Hardware companies are incorporating AI into product names, and giants like Microsoft, Apple, and Google are integrating it into the core of their products and services.</p>
<p>I don’t need to tell you these things. If you are reading this, you likely understand the significant disruption that AI has caused in recent years. However, I think this one will fizzle out in time, like the trends that came before it. AI is undeniably an impressive technology. I use GitHub Copilot myself, and I don’t think the concept will disappear, but I think the hype will. I expect that AI will experience a peak similar to the dot-com bubble did in the early 2000s.</p>
<p>The web remains a key part of our lives 25 years later, but being online is now the norm for a business, not a unique selling point, and that is where I see AI heading. I think we peaked too early with AI; while the technology is impressive, it has deep mistrust.</p>
<p>Firstly, the information that AI provides can’t be trusted, as evidenced by high-profile incidents. AI hallucinates (that is, it returns incorrect information as fact) regularly, and honestly, this problem only worsens. When you have to do the work to fact-check the answer you are getting from AI, is it benefiting you? The lack of trust in AI’s output is a significant problem for AI companies, as it causes AI to be perceived as a novelty rather than a helpful tool.</p>
<p>Another significant issue that AI must address is legal concerns. The major AI models from big and small companies have likely been at least partly trained on data sourced illegally or whose legality is in a grey area. Generative image AI has faced massive backlash from artists and the public for stealing artists’ work. These issues surrounding legality deter professional users and corporations, which, as the highest revenue-generating users, could cause long-term harm to AI-focused companies.</p>
<p>In addition to the legal concerns, AI will also face regulatory challenges. Many high-profile tech, academic, and legislative leaders have <a target="_blank" href="https://en.wikipedia.org/wiki/Pause_Giant_AI_Experiments:_An_Open_Letter">expressed concerns</a> about the potential effects of unregulated AI use on society. These concerns mainly stem from the use of generative AI. As AI improves at creating realistic video, audio, and images, it will become increasingly more complex to distinguish between real and fake content. This poses a significant risk to society, as AI-generated content could be easily used to manipulate people and seed civil unrest. These concerns and challenges suggest that AI will likely face further regulation in the future, similar to the regulation of the web.</p>
<p>Even with my concerns about the AI hype and the challenges it faces as it grows from a novelty to mainstream adoption and deployment, I do think, like with the web and the rise of smartphones, we are standing at the beginning of a monumental shift in how, as a species, we interact with our technology.</p>
<p>One risk I have not mentioned in this article is the direct financial risk. This is mainly because it is hard to quantify. Using trained models at this time holds a lower financial risk. Companies keen on establishing a user base for their models often allow use, especially for experimentation and evaluation, at a very low cost. However, developing and training a model is an expensive investment. You require high-end hardware, which comes with substantial capital costs and operating expenses. AI consumes vast quantities of energy, which, in addition to being costly, also presents environmental challenges. In the current climate crisis, this can’t and shouldn’t be overlooked.</p>
<p>If you are excited about AI's prospects, I encourage you to exercise caution and weigh the risks as you move forward. A significant amount of money is invested in AI, but, as mentioned in this article, I believe it is primarily driven by hype. If AI can provide tangible benefits to your business, product, and/or users, then it is worth exploring. However, as with all things, trying to find a problem that fits the solution is not sustainable in the long term.</p>
<div class="hn-embed-widget" id="cc-license"></div>]]></content:encoded></item></channel></rss>