Static Analysis and AIIf you’re like me, the way you write code has changed significantly in the past year. December 2024 was the first time I decided to use AI to write code, and today it generates most of the code I work on. It also writes the tests and documentation. My job is now focused on reviewing code, and that can get tiring. How can I be confident that the code meets my standards, remains secure, and scales well? The answer is static analysis. Static analysis tools inspect code without executing it, which removes the risk of side effects or security issues that can appear when running tests. This is why static analysis often runs before code execution in continuous integration systems. You may be thinking, “Wait a minute! Don't LLMs perform static analysis on my files to work on them?” The answer is not really. LLMs read text and look for patterns. Because they have been trained on a large amount of code, they can identify patterns that appear desirable or undesirable. Their analysis is non-deterministic, which means you will not always get the same results even when asking the same question of the same code. LLMs also have no semantic understanding of the code they read. Without semantics, any evaluation becomes a guess. Traditional static analysis tools are deterministic and understand semantics. For example, ESLint knows the difference between an identifier named foo and the string "foo". To an LLM, these are similar-looking tokens and the interpretation can shift based on context. This makes static analysis even more important for AI-generated code than for human-written code. Here are some static analysis tools worth integrating, especially if you are deploying AI-generated code: Linters. As the creator of ESLint, I am a strong supporter of using linters. They are especially important for languages that are not compiled before deployment, such as JSON, YAML, and CSS, because they catch syntax errors before production. As capable as LLMs are, I still encounter incorrect syntax in AI-generated code at least once a week. Many linters also flag problematic patterns even when syntax is valid, which makes them essential for AI-generated code. Type checkers. Compiled languages include type checking, but others do not. If you are using a language with a type checker, such as TypeScript for JavaScript, make sure to use it to avoid runtime errors. Accessibility checkers. When working with generated HTML, it is important to verify that the code meets accessibility standards. Accessibility checkers are available both as command line tools and as features built into browser developer tools. Security scanners. Because LLMs are trained on large amounts of code that may not be verified as safe, AI-generated code often contains security vulnerabilities. Use a security scanner that supports your programming language so you do not deploy code that is open to attack. Dependency checkers. You should never let AI select a dependency that has not been vetted. Since LLMs are trained on historical data, they often choose outdated dependencies with known security or licensing issues. Make sure your dependencies are automatically checked before deployment. As AI becomes a larger part of how we write code, static analysis provides a reliable foundation that keeps our work consistent, secure, and maintainable. These tools do not replace the value of human judgment, but they give us confidence that the code we review is structurally sound before we ship it. By pairing AI-assisted development with a strong static analysis pipeline, you set yourself up for faster reviews and higher quality results. Key Takeaways
Stuff I've Enjoyed this Month🎬 The line of code that took down the internet by ThePrimeTime 📝 A complete guide to the HTML number input by Ollie Williams 🎬 Learn the basics of Google Antigravity by Google Antigravity 💻 TOON Format by Johann Schopplich 📝 HTML's best kept secret: The by Den Odell 🎬 Why Anthropic's AI Claude tried to contact the FBI by 60 Minutes 📝 How to programmatically highlight text with the CSS Custom Highlight API by Joe Attardi 💻 VERT.sh What I'm Working On🏠 Real Estate: I had a tenant unexpectedly leave this past month. It's never good to lose a tenant right at the start of winter because people tend not to want to move when it's cold out. However, my property manager thinks he can get it fixed up and rented out fairly quickly. Fingers crossed. Follow my Instagram for real estate photos. 🍞 Bredbox: Bredbox now gives users complete control over their data. You can import, export, clear data, and delete your account. Imports and exports can now be tracked on the new settings page and you'll get emails when operations complete to let you know if things worked. Plus, there's a new logo I'm pretty happy about. 💻 Open Source: I released several new npm packages with utilities that were extracted from Bredbox:
💻 ESLint:
Coaching for Tech Leads and Staff+ EngineersIf you're a tech lead or staff+ engineer, chances are your manager has no experience in your role. While they may be well-intentioned, they may not know how to help you grow in such a challenging position. That's where working with me can help. As a former tech lead and principal engineer at multiple companies, I learned firsthand the ins and outs of these roles. I work with my clients one-on-one to develop their leadership, communication, organization, and problem-solving skills to succeed in the upper ranks of the individual contributor track.
|
A once-per-month newsletter discussing topics important to senior-level software engineers, with a particular focus on frontend technology and leadership.
Working with Legacy Code The term “legacy code” often strikes fear into the hearts of software engineers. While there’s no single definition, IBM describes it as “code that still serves its purpose but was developed using now outdated technologies.” Any successful tech company has some amount of legacy code because that code worked well enough to attract and keep customers. When something is working, especially if it’s difficult to change, the logical choice is often to let it keep running...
npm Security For the past few weeks, an ongoing supply chain attack on npm packages has shaken the JavaScript community. It’s not that npm packages haven’t been compromised before, but this time, the targets were surprising. Attackers went after popular packages maintained by well-known authors, creating the potential for widespread damage. In late August, the popular monorepo tool Nx was compromised, leading to several malicious package versions. These included a postinstall script that...
Code portability If you’ve been following me recently, you’ve probably seen me mention Bredbox, my new application for saving bookmarks. This is the first time in years I’ve built a web application, so I put a lot of thought into the process. My philosophy is to leave as many options open as possible in case I need to change direction later. That’s why I recommend targeting Node.js for JavaScript applications, even if you plan to run them on Deno or Bun. Both Deno and Bun are largely...