Writing Code? Know Your Boundaries.
Today’s developers are cursed blessed with a massive list of libraries and technologies for solving problems. And some of the worst sins against code stem from simply selecting the wrong tool for the job. It’s recently become clear to me that when considering tools, the risk for picking the wrong tool for the job is strongest near the boundaries. Consider some common technologies for building web applications today. Each technology has a specific purpose.
- HTML provides semantic markup of our content
- CSS separates our styling from our markup
- JavaScript provides behavior
- Server-side languages manage the business logic
- SQL is useful for RDBMS data access and manipulation
And here’s the thing: It’s the boundaries and interactions between technologies that get people in trouble. Let’s discuss the interactions between each of these technologies and common situations where developers select the wrong tool for the job.
HTML and JavaScript Boundary
Avoid putting HTML in JavaScript strings for “poor man’s templating” like this.
Note how the HTML for generating a row is buried within the for loop and set to a variable called carRows.
It’s tempting to put HTML in a JavaScript string so that you can dynamically inject HTML onto the page. But markup should ideally be native HTML. When selecting a templating solution, look for one the utilizes plain old HTML for the template source. Both KnockoutJS and AngularJS templates use this approach. If you’re storing HTML in .js files, think twice – JavaScript is typically the wrong tool for storing markup since you lose the benefits of staying native (code coloring, syntax checking, etc).
On the other side of the coin, avoid placing complex JavaScript on DOM elements in HTML:
[pageview url=”http://jsfiddle.net/housecor/3cXwh/embedded/html” height=”100″]
It’s tempting to put JavaScript directly in your HTML. But this mixes concerns by injecting behavior directly into your markup and eliminates the opportunity for caching and reuse. The unobtrusive JavaScript movement really helped diminish this problem, but new frameworks like Knockout and Angular have started pushing JavaScript back into HTML markup. There’s some clear benefits to simple declarative markup in HTML since it’s more discoverable and readable when the bindings are simple. But be careful, when much beyond simple declarative bindings is involved, JavaScript belongs in .JS files and HTML belongs in .html files.
HTML and SQL Boundary
Here’s two simple examples of ignoring the important boundary between data and HTML:
SELECT '<strong>' + Username + '</strong>' FROM Users
Username stored in database with HTML styling
Relational databases should contain raw normalized data that can be leveraged for a variety of purposes. Thus, storing HTML in the DB or injecting HTML in query results as shown above is problematic. It binds the presentation and data storage together making reuse difficult.
One common exception is content management systems where users must be able to store and manage HTML which is persisted in the database. This scenario sacrifices data reuse and normalization for end user management power. Think very carefully about saddling data with presentation concerns since it radically reduces flexibility by “hard coding” in the presentation. Mixing presentation and data should be avoided. They’re separate concerns and should be treated as such.
HTML and CSS Boundary
It’s a very similar story with the HTML/CSS interaction. Avoid doing this:
[pageview url=”http://jsfiddle.net/housecor/6gT8f/embedded/html” height=”75″]
It’s tempting to place styles inline in HTML, but this mixes semantic markup with style. These are separate concerns and doing so eliminates the opportunity for caching and reuse of CSS and hinders maintenance down the road. The DRY principle applies here: If you’re going to use a style in more than one spot, it pays to declare the style once in a separate stylesheet.
SQL and Server-side Language Boundary

It’s easy to create highly dynamic SQL in a server-side language like C# using strings to generate SQL statements, but stored procedures and ORMs often provide a safer and more elegant approach to generating dynamic SQL. Writing dynamic SQL in strings opens the door to SQL injection vulnerabilities and eliminates the opportunity for DBAs to manage and enhance the performance of such queries. SQL in strings also introduce a high risk for run-time errors in the application when schema changes occur. ORMs provide a strongly typed interface to the database and will thus fail to compile when the schema becomes out of sync with existing database queries.
JavaScript / Server-side Language Boundary
Writing dynamic JavaScript in a string on the server leads to code like this.
string googleAnalyticsScript = @"var _gaq = _gaq || [];
_gaq.push(['_setAccount', '" + googleAnalyticsKey + @"']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script');
ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ?
'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();";
This is the most common tool misuse I see: using a server-side language to generate dynamic JavaScript. In the vast majority of use cases JavaScript should remain in a .JS file. JSON can be returned from the server to provide dynamism. I won’t go into a specific example here, but check out this blog post on the JavaScript configuration object pattern if you’re curious how to pull off highly dynamic JavaScript without resorting to generating it via strings on the server.
So before you dive into writing that next line of code, think twice – are you near a boundary? Does a more elegant solution exist on the other side of the boundary? Clean coders should strive to stay native: – the file extension should be a good indicator of the technology that lies within.
Stay Native
Of course, the importance of staying native isn’t at all specific to JavaScript. There are a variety of opportunities to find yourself struggling with strings when there’s a less painful alternative that involves staying native. The bottom line is, avoid using one language to write another language or format via strings. Creation of these formats dynamically is a solved problem in most popular languages these days, so be sure to leverage libraries to generate such formats. A good rule of thumb is to strive for one language per file. Generating any of these items via strings requires the reader to understand the interactions of two technologies simultaneously. And doing so often breaks tooling support as well. So if you notice you have two languages in one file, think twice about how one could be eliminated by solving the problem in a different, and more elegant way.
If you’re interested in learning more about writing clean code, check out my new Pluralsight course: Clean Code: Writing Code for Humans
See other boundaries to consider? Chime in below or join the discussion on Hacker News.
Comments
Anonymous
Andy — 2013-10-08
`SELECT ‘‘ + Username + ‘‘ FROM Users` is likely to fail, because that query is looking for a field named `Cory` on the `Users` table. Instead, the example should be something more along the lines of “SELECT `Name` FROM `Users` WHERE `Name` = ‘” + Username + “‘;” where you are extracting the content shown in the picture that followed.
Patrice — 2013-10-10
Indeed, the SQL command is wrong and not respect the valid syntax :
SELECT ‘‘ + Username + ‘‘ FROM Users
Below the valid syntaxt:
SELECT name FROM Users Where name = ‘Cory‘;
Anonymous
Dan — 2014-07-02
What’s your opinion on html templating engines, such as Handlebars and Razor? Does this make more clean reusable code or just violate the boundaries?


