software(15/1)
Development patterns with ai
In Hrishi Olickel’s LLM Hacker Guide he describes some of the ways his thoughts about the development process have changed since working closely with Large Language Models (LLMs). Development Process Hrishi explores the ways that the development process has changed. He offers two other in-between processes, but below is the traditional and the new AI methodology. flowchart LR Write -- Compile -- Run flowchart LR Chat -- Play -- Loop -- Nest Traditional development is about writing code, compiling it, and running it.…
When to build your own software
Mike outlines the transition between a custom-build workflow using proprietary software and the building of custom software. He calls it The Spreadsheet Gap. This is exactly the same gap I’ve witnessed where I currently work; a financial services firm. My customers request Excel features be built into our non-Excel website. Sometimes this is simple, but more frequently there is disappointment when they find that a “simple” Excel feature translates into months of development time.…
Pick a software language for your project
I’ve read many articles from software developers about the value of learning multiple software languages. It may not be for everyone, but that’s been a good path for me. I enjoy the challenge of learning new idioms, solving challenges in new ways, and reading the codebases of my favorite tools. One problem these suggestions don’t address is how to make choices after you’ve learned a half-dozen languages. If your employer runs a MSSQL/.…
Vscode tips
ℹ️ Use `CTRL-SHIFT-SPACE` to show constructor arguments while creating a class. Extremely useful when your trying to wire properties to the correct argument.
Choosing a tech stack
Software projects often get postponed while I decide on the tech stack. What kind of data storage? What programming language? Which framework, if any? My abundant choices sometimes paralyze me from actual building. There are many stories one might approach software development, but one that I might benefit from goes, “code is cheap. Build it with what you know and, if it needs to be improved, rebuild it.” Julia Evan’s three points from Ines Sombra explores this in the reverse; what motivates a system change:…
Unix philosophy
A number of maxims have gained currency among the builders and users of the UNIX system to explain and promote its characteristic style: Make each program do one thing well. To do a new job, build afresh rather than complicate old programs by adding new “features.” Expect the output of every program to become the input to another, as yet unknown, program. Don’t clutter output with extraneous information. Avoid stringently columnar or binary input formats.…
Why specialize as a software developer
Specialization for role advancement Listening to my colleagues chat about a recent interviewee, I came to a realization about obtaining the ‘senior’ bit of ‘senior software engineer.’ Longevity in the domain or breadth of knowledge will never achieve a promotion because ‘senior’ means someone who is exceptionally well versed at [pick your language or framework]. Sure, a senior needs to have high-quality communication skills, but that won’t get them hired if they can’t demonstrate an esoteric level of knowledge in [pick your language or framework].…
Javascript build tooling is a mess
It’s refreshing to read Julia’s article about esbuild. I’ve found the JavaScript build tooling to be an obtuse, obscure mess ever since I first began to use it years ago. When that’s all a person knows, like many front-end developers I’ve met, then it’s taken for granted that this is a necessary evil. But when you’ve used clean, simple back-end CLI’s like dotnet or scaffolded your project’s pipeline with a Makefile, the wreckage that is JavaScript bundling and transpiling feels gross.…
Organize subscription chains with pipes
Often, two or more observables depend upon one another for execution. This can lead to chained subscriptions. Take this real-world example: this.openInvalidPeriodDialog$(dialog).subscribe(dialog => { dialog.afterClosed().subscribe(jumpToLatestPeriod => { if (jumpToLatestPeriod) { this.periodService.getLatestPeriod().subscribe(latestPeriod => { this.analysisService.getPreliminaryPeriodId$(federalReserveId, analysisId, latestPeriod.id) .subscribe(periodId => this.sessionService.setQualitativePeriod(periodId ?? latestPeriod.id)) }); } }); }); The multiple subscribes() might be written in a more descriptive chain with a pipe and use of switchMap() and filter(). this.openInvalidPeriodDialog$(rejectionDialog) .pipe( switchMap(invalidPeriodDialog => invalidPeriodDialog.afterClosed()), filter(jumpToLatestPeriod => jumpToLatestPeriod), switchMap(() => this.…
Simplify loop with iterator swap
When operating on two or more collections you may encounter loops that filter one collection by another. Say we have a collection of dinners and a collection of ingredients. We want to find out, given our ingredients, which dinners are using at least one ingredient. We might write our filter like this: const dinners = this.getDinnerRecipes(); const ingredients = this.getIngredients(); const dinnerIds = ingredients.map(i => i.dinnerId); const dinnerOptions = dinners.filter(dinner => { if (dinnerIds.…
Save unfinished notes in local storage
When I publish content to my site I sometimes get nervous that the work I’ve written into the publish form will be lost. Jan-Lukas has written a straightforward Javascript snippet to store my work locally so it will not be lost. Thanks! Simply cache form fields in localStorage
Display backlink preview on hover
The combination of microformat2 h-entry and backlinks is potent. Each note page that’s marked up with a e-content microformat2 property can be retrieved via fetch() and displayed as a preview elsewhere on the site. No database required; the website is the API. With these two snippets you can implement dynamic backlink functionality on pretty much any webpage. With a little standardization (mostly complete by the microformat2 standard), one could support backlinks across websites.…
One subscription per resource
Here’s my subscription progression for the qrm-category-container root component. Let me know if this is headed in the right direction. Stage One - Current Code The root container creates a subscription in onInit() that fires whenever fedId or QRM periodId changes, like so: combineLatest([this.sessionQuery.federalReserveId$, this.sessionQuery.qualitativePeriodId$]) .subscribe(([fedId, qualitativePeriodId]) => { this.qualitativePeriodId = qualitativePeriodId; this.refreshViewModel(fedId, qualitativePeriodId, this.viewCustomerData, this.categoryId); }); That’s not too bad, right? Consider what happens in refreshViewModel()… refreshViewModel(federalReserveId: number, periodId: number, viewCustomerData: boolean, categoryId): void { this.…
Smart components observe state over input
In component design there are two buckets, smart and dumb components. Smart components are keepers of data models and reactive to changes. Dumb components render explicit data models to views. Dumb components benefit from the explicit interface created by a clear set of inputs. Smart components, however, can get into a lot of trouble if they depend on mutable inputs for their data models. While it seems easy to add an onChanges() function to child smart components to re-render based on changes to their inputs, this dependency can have unexpected consequences.…
Angular maxims
This is an incomplete list of maxims I’ve gleaned while working on Angular/RxJS development. favor identifier over index simplify loop with iterator swap smart components observe state over input organize subscription chains with pipes one subscription per resource distinguish series and one time observables 💬 RxJS has a reputation for being complex, hard to understand, and hard to use. A deserved reputation, to be honest. I’ve used RxJS in a project to great effect, it made an impossible problem possible, but getting your head around it isn’t trivial.…
Favor identifier over index
If there are several arrays of data retrieved from different service calls it can be tempting to iterate over them all by index. const columnsFirst = this.dataService.getFirstData(); const columnsSecond = this.dataService.getSecondData(); columnsTotal = []; for (var i = 0; i < columnsFirst.length(); i++) { const total = columnsFirst[i].value + columnsSecond[i].value; columnsTotal.append(total); } return columnsTotal; Iteration by index is prone to many errors, however. The order of each column array must match, their lengths must equal (although this can be overcome with a null check), and it’s not clear to other developers why there’s a hard dependency between these arrays without further investigation.…