Last Friday we had the day off, so I walked around our local zoo by myself. It was great! But I’m back in the saddle today, and this promises to be a very busy week. There’s always time for reading though, so please enjoy what I consumed today.
[blog] 4 Reasons to Use Angular for Your Next Web App. Love it. There are good reasons, but I also appreciate the quiet confidence of those using something good, who aren’t personally crushed if you don’t make the same choice.
[blog] The four tenets of SOA revisited. yes, tech is changing faster now than likely at any time in history. But there are plenty of durable ideas that stick around. Mark is starting a look at service oriented architecture principles.
[article] “Good enough” code is just not good enough. There are times when “good enough” is ok, but continuously adopting that approach doesn’t yield excellence in the long run.
##
Want to get this update sent to you every day? Subscribe to my RSS feed or subscribe via email below:
If you have a choice, you should test software against the real thing. The second best option is to use a “fake” that implements the target service’s API. In the cloud, it’s straightforward to spin up a real instance of a service for testing. But there are reasons (e.g. cost or speed) or times (e.g. within a CI pipeline, or rapid testing on your local machine) when an emulator is a better bet.
Let’s say that you wanted to try out Google Cloud Spanner, and it’s useful change streams functionality. Consider creating a real instance and experimenting, but you have an alternative option. The local emulator just added support for change streams, and you can test the whole thing out from the comfort of your own machine. Or, to make life even easier, test it out from a free cloud machine.
With just a Google account (which most everyone has?), you can use a free cloud-based shell and code editor. Just go to shell.cloud.google.com. We’ve loaded this environment up with language CLIs for Java, .NET, Go, and others. It’s got the Docker daemon running. And it’s got our gcloud CLI pre-loaded and ready to go. It’s pretty cool. From here, we can install the Spanner emulator, and run just a few shell commands to see the entire thing in action.
Let’s begin by installing the emulator for Cloud Spanner. It takes just one command.
Then we start up the emulator itself with this command:
gcloud emulators spanner start
After a couple of seconds, I see the emulator running, and listening on two ports.
Great. I want to leave that running while having the freedom to run more commands. It’s easy to spin up new tabs in the Cloud Shell Editor, so I created a new one.
In this new tab, I ran a set of commands that configured the gcloud CLI to work locally with the emulator. The CLI supports the concept of multiple configurations, so we create one that is emulator friendly. Also note that Google Cloud has the idea of “projects.” But if you don’t have a Google Cloud account, you’re ok here. For the emulators, you can use a non-existent value for “project” as I have here.
gcloud config configurations create emulator
gcloud config set auth/disable_credentials true
gcloud config set project local-project
gcloud config set api_endpoint_overrides/spanner http://localhost:9020/
It’s time to create a (local) Spanner instance. I ran this one command to do so. It’s super fast, which makes it great for CI pipeline scenarios. That second command sets the default instance name so that we don’t have to provide an instance value in subsequent commands.
It’s time to turn on change streams, and this takes an extra step. It doesn’t look like I can smuggle utility commands through the “execute-sql” operation, so we need to run a DDL statement instead. Note that you can create change streams that listen to specific tables or columns. This one listens to anything changing in any table.
I’m now going to open a third tab in the Cloud Shell Editor. This is so that we can continuously tail the change stream results. We’ve created this nice little sample project that lets you tail the change stream. Install the app by running this command in the third tab.
go install github.com/cloudspannerecosystem/spanner-change-streams-tail@latest
Then, in this same tab, we want the Go SDK (which this app uses) to look at the local emulator’s gRPC port instead of the public cloud. Set the environment variable that overrides the default behavior.
export SPANNER_EMULATOR_HOST=localhost:9010
Awesome. Now we start up the change stream app with a single command. You should see it start up and hold waiting for data.
Back in the second tab (the first should still be running the emulator, the third is running the change stream tail), let’s add a new record to the Spanner database table. What SHOULD happen is that we see a change record pop up in the third tab.
gcloud spanner databases execute-sql example-db \
--sql="INSERT INTO Albums (SingerId, AlbumId, AlbumTitle) VALUES (2, 2, 'Go, Go, Go')"
Sure enough, I see a record pop into the third tab showing the before and after values of the row.
You can mess around with updating records, deleting records, and so on. A change stream is powerful for event sourcing scenarios, or simply feeding data changes to downstream systems.
In this short walkthrough, we tried out the Cloud Shell Editor, spun up the Spanner emulator, and experimented with database change streams. All without needing a Google Cloud account, or installing a lick of software on our own device. Not bad!
[article] Improving Developer Experience Drives Profitability. You can ignore (important) outcomes like happier developers and high-quality software if you want. Even if you invest in dev experience for financial motives, the effort will be appreciated.
[article] Product-Focused Reliability for SRE. Outstanding piece from the Google SRE team that proposes a product-focused model for defining SLOs and service overall.
I’m wiped after a busy day; it’s the 1:1 conversations that really do it to me. I’m an introvert, so it takes extra effort to dial up the listening, engaging, and emoting. Worth it, but exhausting. My “relaxation” time often involves stealing a couple minutes to read the items below.
[blog] Gemma, Ollama and LangChainGo. I’ve seen a lot of experiments with Gemma. Here, Eli shows how straightforward it is to run locally on your machine.
[article] How Netflix Really Uses Java. The presentation and transcript includes lots of details about what’s running at Netflix, their key tech choices, and what they’re excited about.
[blog] Monitoring your latest app release just got easier. If you’re like me, you have very little patience for finicky mobile apps. This new Firebase dashboard lets you see key metrics in real-time after a release, which means you can fix things faster, and keep users happier.
[article] Periodic Face-to-Face. Martin Fowler says that even remote-first teams need face to face time to build trust, uncover ideas, and confirm direction.
[blog] How to prevent lateral movement techniques on Google Cloud. You don’t want attackers navigating across the network to find vulnerable resources. This post explores recent research from Palo Alto Networks, and how to avoid cloud misconfigurations.
##
Want to get this update sent to you every day? Subscribe to my RSS feed or subscribe via email below:
Today’s list has some fun content to chew on and consider more deeply. Look at items on productivity, interviewing, and figuring out AI for your company.
[blog] Build A Human-Centered Productivity Strategy. I’ve shared a lot here about developer productivity, but obviously it relates to a much broader discussion of how we work. This Forrester blog (which links to a $$ report) has good details on a better approach.
[article] How Capable Leaders Navigate Uncertainty and Ambiguity. Speaking of interviewing, check out these excellent interview questions for those trying to judge whether a candidate is good at navigating uncertain and complex situations.
[article] How to cut through the AI noise. Enterprise companies making CapEx bets on AI-based tech seems … risky. There’s a lot of learning and scaling going on, and public cloud is designed for that.
Did you have a good weekend? I think I did. This work week started fast, so the weekend is a distant memory. I really enjoyed today’s reading list, and I hope you do too.
[blog] How startups beat incumbents. Simply outstanding post. Study this for a way to think about disrupting incumbents, while also protecting yourself from disruption.
[article] What Makes a Code Change Easier to Review? Relatively short post that explores a paper about code changes. Specifically, it highlights the change description, size, and history as important factors.
Today’s reads are fairly Google-centric. On Fridays, I prepare 1-2 different newsletters, so I’m browsing through lots of that sort of content. Adjust your expectations accordingly!
[blog] go run. This simple command lets Go developers run their app without any fuss. Chris writes a post celebrating its sneaky power.
[article] 3 Ways to Help Struggling Open Source Communities. It’s not someone else’s job to keep the open source we depend on healthy. It’s all of us, right? This article looks at how to keep showing support to your favorite community.
[blog] gemini-cli: Access Gemini models from the command-line. Cool experiment that I may actually take advantage of. Eli wanted to feed info about old blog posts to create a “related posts” feature for his blog. So he built a tool that any of us could try.
[blog] Guide to Function Calling with Gemini and Google Apps Script. There’s no one “right” pattern for feeding data into generative AI-powered apps. Maybe you fine-tune a model. Or use a RAG-style architecture to feed extra context. And function-calling is another exciting option.
We had some fun news today—more AI models that everyone can use—but lots of other things are going on too. My reading list rarely includes “news”; I skim those headlines, but I care more about long-form pieces that teach me something. Today’s list is mostly about those items.
[blog] Formula Pie Charts in Google Sheets. Who doesn’t like pie? This is a cool way to get mini pie charts in the rows of your spreadsheet.
[blog] The Best of Both Angular Worlds: Standalone & Modules Combined. Admittedly, front-end frameworks still intimidate me. Just give me some JavaScript and CSS and I’m happy. Angular has gotten easier to use over the years, and this post is a good example.
[article] Kubernetes Predictions Were Wrong. I remember when folks (and I likely said it myself) claimed that Kubernetes would be invisible by now. Just melted into the infrastructure and only a few folks would care about it. Not the case, at least not yet.
I’m skeptical of anything that claims to make difficult things “easy.” Easy is relative. What’s simple for you might draw blood from me. And in my experience, when a product claims to make something “easy”, it’s talking about simplifying a subset of the broader, more complicated job-to-be-done.
So I won’t sit here and tell you that generative AI makes app modernization easy. Nothing does. It’s hard work and is as much about technology as it is psychology and archeology. But AI can make it easier. We’ll take any help we can get, right? I count at least five ways I’d use generative AI to make smarter progress on my modernization journey.
#1 Understand the codebase
Have you been handed a pile of code and scripts before? Told to make sense of it and introduce some sort of feature enhancement? You might spend hours, days, or weeks figuring out the relationships between components and side effects of any changes.
Generative AI is fairly helpful here. Especially now that things like Gemini 1.5 (with its 1 million token input) exist.
I might use something like Gemini (or ChatGPT, or whatever) to ask questions about the code base and get ideas for how something might be used. This is where the “generative” part is handy. When I use the Duet AI assistance in to explain SQL in BigQuery, I get back a creative answer about possible uses for the resulting data.
In your IDE, you might use Duet AI (or Copilot, Replit, Tabnine) to give detailed explanations of individual code files, shell scripts, YAML, or Dockerfiles. Even if you don’t decide to use any generative AI tools to write code, consider using them to explain it.
#2 Incorporate new language/framework features
Languages themselves modernize at a fairly rapid pace. Does your codebase rely on a pattern that was rad back in 2011? It happens. I’ve seen that generative AI is a handy way to modernize the code itself while teaching us how to apply the latest language features.
For instance, Go generics are fairly new. If your Go app is more than 2 years old, it wouldn’t be using them. I could go into my Go app and ask my generative AI chat tool for advice on how to introduce generics to my existing code.
Usefully, the Duet AI tooling also explains what it did, and why it matters.
I might use the same types of tools to convert an old ASP.NET MVC app to the newer Minimal APIs structure. Or replace deprecated features from Spring Boot 3.0 with more modern alternatives. Look at generative AI tools as a way to bring your codebase into the current era of language features.
#3 Improve code quality
Part of modernizing an app may involve adding real test coverage. You’ll never continuously deploy an app if you can’t get reliable builds. And you won’t get reliable builds without good tests and a CI system.
AI-assisted developer tools make it easier to add integration tests to your code. I can go into my Spring Boot app and get testing scaffolding for my existing functions.
Consider using generative AI tools to help with broader tasks like defining an app-wide test suite. You can use these AI interfaces to brainstorm ideas, get testing templates, or even generate test data.
In addition to test-related activities, you can use generative AI to check for security issues. These tools don’t care about your feelings; here, it’s calling out my terrible practices.
Fortunately, I can also ask the tool to “fix” the code. You might find a few ways to use generative AI to help you refactor and improve the resilience and quality of the codebase.
#4 Swap out old or unsupported components
A big part of modernization is ensuring that a system is running fully supported components. Maybe that database, plugin, library, or entire framework is now retired, or people don’t want to work with it. AI tools can help with this conversion.
For instance, maybe it’s time to swap out JavaScript frameworks. That app you built in 2014 with Backbone.js or jQuery is feeling creaky. You want to bring in React or Angular instead. I’ve had some luck coaxing generative AI tools into giving me working versions of just that. Even if you use AI chat tools to walk you through the steps (versus converting all the code), it’s a time-saver.
The same may apply to upgrades from Java 8 to Java 21, or going from classic .NET Framework to modern .NET. Heck, you can even have some luck switching from COBOL to Go. I wouldn’t blindly trust these tools to convert code; audit aggressively and ensure you understand the new codebase. But these tools may jump start your work and cut out some of the toil.
#5 Upgrade the architecture
Sometimes an app modernization requires some open-heart surgery. It’s not about light refactoring or swapping a frontend framework. No, there are times where you’re yanking out major pieces or making material changes.
I’ve had some positive experiences asking generative AI tools to help me upgrade a SOAP service to REST. Or REST to gRPC. You might use these tools to switch from a stored procedure-heavy system to one that puts the logic into code components instead. Speaking of databases, you could change from MySQL to Cloud Spanner, or even change a non-relational database dependency back to a relational one. Will generative AI do all the work? Probably not, but much of it’s pretty good.
This might be a time to make bigger changes like swapping from one cloud to another, or adding a major layer of infrastructure-as-code templates to your system. I’ve seen good results from generative AI tools here too. In some cases, a modernization project is your chance to introduce real, lasting changes to a architecture. Don’t waste the opportunity!
Wrap Up
Generative AI won’t eliminate the work of modernizing an app. There’s lots of work to do to understand, transform, document, and rollout code. AI tools can make a big difference, though, and you’re tying a hand behind your back if you ignore it! What other uses for app modernization come to mind?