homepage update; blog: why code comments?
This commit is contained in:
parent
52de91eecc
commit
371fc2765c
5 changed files with 189 additions and 7 deletions
104
src/content/blog/2024-01-16-why-code-comments.md
Normal file
104
src/content/blog/2024-01-16-why-code-comments.md
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
---
|
||||
title: Why code comments?
|
||||
date: 2024-01-16T21:59:17.367Z
|
||||
slug: 2024-01-16-why-code-comments
|
||||
author: Thomas Wilson
|
||||
|
||||
---
|
||||
Let's get into some real 2018 Wilson shit and talk about writing comments in code.
|
||||
|
||||
Comments are bits of text that developers leave in code files that are explicitly marked as "please ignore" to the computer who reads the computer instructions.
|
||||
|
||||
They are written messages from one developer to another.
|
||||
|
||||
Why would you leave a comment? One of the notorious (if not impactful) texts of software engineering, [Clean Code](https://www.oreilly.com/library/view/clean-code-a/9780136083238/), holds that comments are a failure of code. It should be clear what code is doing, and comments are a crutch that prevent code from being Clean.
|
||||
|
||||
I was recently reading [A Philosophy of Software Design](https://www.amazon.co.uk/Philosophy-Software-Design-John-Ousterhout/dp/1732102201) (sorry about the Amazon link). The author has taught software engineering to undergraduates in American institutes, and noticed some recurring patterns in how people (novices, especially) create their own shortfalls. They put into words some of the heuristics I've shaped over the years.
|
||||
|
||||
I wanted to write down some of those things, and give some examples of what I think about when I am writing comments.
|
||||
|
||||
## Name and Date
|
||||
|
||||
Always name and date a comment.
|
||||
|
||||
A comment written last month is different to something that's been around for a year. A comment left by your good colleague Wilson might read differently to something left by another engineer.
|
||||
|
||||
As a bonus, if you feel like you don't want to attach your name to a comment (e.g. it might not be quite true, or might be a cop-out), then this is a good way yo make you encounter those feelings.
|
||||
|
||||
As a bonus bonus point, I preface my initials with a `--`, to make a pretty easy `grep`-able string. Here's a nice one-liner: `ag -i '\-\-tjw' ./`. As of right now, I have committed 32 comments in 19 files since November 2023
|
||||
|
||||
```js
|
||||
// It would be nice to use the Intl library here --TJW 2023-01-15
|
||||
export const formatDate = (date) => externalLibrary.format(date, 'yyyy-mm-dd')
|
||||
```
|
||||
|
||||
|
||||
## Name the uncertainty
|
||||
|
||||
Label code that is likely to change soon. ("Soon" becomes easy to define when you name and date everything).
|
||||
|
||||
Label code which contains known problems,
|
||||
|
||||
Clearly label problematic patterns which should not worth copy-pasted. If we find ourselves in an unfamiliar part of the codebase, we might copy-paste something nearby to get going. I think copy-pasting without critically evaluating the quality of code (hard if you don't have context) is a serious pathway to how problems proliferate.
|
||||
|
||||
```js
|
||||
export class User {
|
||||
// The User model shouldn't be coupled to encrpytionLibrary
|
||||
// if you find yourself here, please consider extracting this
|
||||
// to a separate package or module --TJW 2024-01-15
|
||||
static encryptPassword(password: string): string {
|
||||
return encryptionLibrary.encrypt(password);
|
||||
}
|
||||
|
||||
// We plan to replace this with a 'chosenName' field soon
|
||||
// --TJW 2005-10-12
|
||||
get fullHumanName(): string {
|
||||
return [this.firstName, this.familyName].join(' ');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Name the change or non-compliance
|
||||
|
||||
Similarly, if you're writing code which doesn't fit a norm or expected pattern, then call it out.
|
||||
|
||||
This stops the copy-paste problem above, but largely serves to highlight variation of patterns in the codebase.
|
||||
|
||||
It there is going to be variation (things will never be consistent everywhere) - it's good to have the context about *why* this decision was made.
|
||||
|
||||
There's a meaningful difference between someone not knowing the best practice, and someone knowingly deviating from it.
|
||||
|
||||
```js
|
||||
// We are injecting the currency here, but normally we would
|
||||
// take it from the Order. We're passing it in as an argument
|
||||
// because we might need to calculate tax differently based
|
||||
// on locale --TJW 2024-01-16
|
||||
export const getDeliveryCost(order: Order, currency: Currency): number => {
|
||||
..
|
||||
}
|
||||
```
|
||||
|
||||
## Give the dates in human-form
|
||||
|
||||
If you're doing any kind of date and time maths (including conversion), write out what you have in human language.
|
||||
|
||||
Tell me "this is 9am on a Monday in GMT in London" or "this is one second later".
|
||||
|
||||
You're probably okay not to name and date these.
|
||||
|
||||
```js
|
||||
|
||||
it('should handle time-zone conversion', () => {
|
||||
// 09:00 GMT the day before GMT-BST switch over
|
||||
const beforeSwitch = new Date('2024-03-30T09:00+01:00')
|
||||
// 09:00 BST the day of the GMT-BST switch
|
||||
const onSwitch = new Date('2024-03-31T09:00Z)
|
||||
|
||||
// ...
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -16,10 +16,10 @@
|
|||
<section class="section thomaswilson-strapline">
|
||||
<h1 class="title">Thomas Wilson</h1>
|
||||
<p>
|
||||
I'm a software engineer who loves the messy craft of leading teams and
|
||||
building software. I like finding the tension between
|
||||
<i>minimal</i> and <i>complete</i>. I build good things with good people
|
||||
for good companies.
|
||||
<span class="strapline-animated" id="statement-1">I am a software engineer who loves the craft of building quality software, </span>
|
||||
<span class="strapline-animated" id="statement-2">the messy-ness of working with people,</span>
|
||||
<span class="strapline-animated" id="statement-3">and the balance between <i>minimal</i> and <i>complete</i> products.</span>
|
||||
<span class="strapline-summary">I build good things with good people for good companies.</span>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
|
|
@ -27,13 +27,14 @@
|
|||
<h2>My work</h2>
|
||||
{#if isWorkExpanded}
|
||||
<ul transition:slide="{{ duration: 220 }}">
|
||||
<li>Right now I am a Senior Software Engineer at <a href="https://www.laka.co.uk" target="_blank" rel="noopener noreferrer">Laka</a>. We're building web tools to un<span class="censor">fuck</span> insurance</li>
|
||||
<li>
|
||||
Right now I'm leading software engineering at <a
|
||||
I spent three years building and leading the Software Engienering team at<a
|
||||
class="oxwash"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="https://www.oxwash.com">Oxwash</a
|
||||
>, we're building the sustainable and scalable future of laundry.
|
||||
>, where we built tools for the sustainable and scalable future of laundry.
|
||||
</li>
|
||||
<li>
|
||||
I build full-stack software for the web, especially with TypeScript,
|
||||
|
|
@ -41,7 +42,7 @@
|
|||
</li>
|
||||
|
||||
<li>
|
||||
I lead teams with domain driven design, and agile (with a little 'a')
|
||||
I like domain driven design, and agile (with a little 'a')
|
||||
opinions about delivery and collaboration.
|
||||
</li>
|
||||
|
||||
|
|
@ -199,4 +200,62 @@
|
|||
li {
|
||||
padding-bottom: 0.3rem;
|
||||
}
|
||||
|
||||
/** Create a class called censor which places a black bar over the text*/
|
||||
.censor {
|
||||
position: relative;
|
||||
color: transparent;
|
||||
text-shadow: 0 0 3px rgba(0,0,0,0.7);
|
||||
}
|
||||
|
||||
.censor::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 55%;
|
||||
width: 100%;
|
||||
height: 8px;
|
||||
background-color: black;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
|
||||
@keyframes statementAppear {
|
||||
0% {
|
||||
opacity: 0.1;
|
||||
transform: translateY(-20px)
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0px)
|
||||
}
|
||||
}
|
||||
|
||||
.strapline-summary {
|
||||
font-weight: 400;
|
||||
}
|
||||
.strapline-animated {
|
||||
animation-fill-mode: forwards;
|
||||
opacity: 0.15;
|
||||
transform: translateY(-10px)
|
||||
}
|
||||
|
||||
#statement-1 {
|
||||
animation-name: statementAppear;
|
||||
animation-delay: 0.5s;
|
||||
animation-duration: 1.5s;
|
||||
}
|
||||
|
||||
#statement-2 {
|
||||
animation-name: statementAppear;
|
||||
animation-delay: 1.4s;
|
||||
animation-duration: 1.5s;
|
||||
}
|
||||
|
||||
#statement-3 {
|
||||
animation-name: statementAppear;
|
||||
animation-delay: 2.3s;
|
||||
animation-duration: 1.5s;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
9
src/routes/blog/[slug]/+layout.svelte
Normal file
9
src/routes/blog/[slug]/+layout.svelte
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<script>
|
||||
import "../../../styles/prism.css";
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<script src="/prism.js"></script>
|
||||
</svelte:head>
|
||||
|
||||
<slot />
|
||||
3
src/styles/prism.css
Normal file
3
src/styles/prism.css
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
/* PrismJS 1.29.0
|
||||
https://prismjs.com/download.html#themes=prism-solarizedlight&languages=markup+css+clike+javascript */
|
||||
code[class*=language-],pre[class*=language-]{color:#657b83;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{background:#073642}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{background:#073642}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto;border-radius:.3em}:not(pre)>code[class*=language-],pre[class*=language-]{background-color:#fdf6e3}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#93a1a1}.token.punctuation{color:#586e75}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#268bd2}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string,.token.url{color:#2aa198}.token.entity{color:#657b83;background:#eee8d5}.token.atrule,.token.attr-value,.token.keyword{color:#859900}.token.class-name,.token.function{color:#b58900}.token.important,.token.regex,.token.variable{color:#cb4b16}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}
|
||||
7
static/prism.js
Normal file
7
static/prism.js
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue