Category: Software

UI components: Angular vs React

Please don't reinvent JavaScript in your web framework

I’ve been building web UIs in Angular and React for the last few years, and I’ve started to greatly prefer React. Extracting and using UI components is just easier and, for lack of a better word, more JavaScripty.

Extracting components in React

Say I notice that I’m creating multiple <span> elements with the same class and icon:

function Main() {
  return (
    <div>
      <span class="alert-tag"><i class="fa alert"></i>foo</span>
      <span class="alert-tag"><i class="fa alert"></i>bar</span>
      <span class="alert-tag"><i class="fa alert"></i>baz</span>
    </div>
  );
}

It’s trivial to refactor this repeated element into its own <Alert> component function within the same file:

function Main() {
  return (
    <div>
      <Alert>foo</Alert>
      <Alert>bar</Alert>
      <Alert>baz</Alert>
    </div>
  );
}

function Alert({ children }) {
  return (<span class="alert-tag"><i class="fa alert"></i>{children}</span>);
}

Super easy, uses JavaScript’s native language constructs, and I was able to do it all within the same file (but I can easily move Alert() elsewhere for wider re-use if needed). It’s just like extracting a function in a “regular” programming language, it’s something you do without even thinking about it.

Quick T-SQL Regression Testing

Using CHECKSUM() and CHECKSUM_AGG()

Here’s something I’ve found useful in SQL Server, but it should apply in any DBMS with checksum functions. Next time you’re refactoring some database objects and you want to do some regression testing, give the CHECKSUM (MSDN) and CHECKSUM_AGG (MSDN) functions a try.

CHECKSUM and CHECKSUM_AGG

They behave pretty much as you would expect; CHECKSUM returns 1 checksum given 1 row, and CHECKSUM_AGG is an aggregate function that returns 1 checksum given multiple checksum rows. Between the two of them, you can get a checksum for any arbitrary collection of data:

-- Returns 2 rows with 2 columns
SELECT Field1, Field2
FROM (VALUES ('foo','bar'),('baz','foo')) TempTable(Field1,Field2)

-- Returns 2 rows with 1 checksum column
SELECT CHECKSUM(Field1,Field2)
FROM (VALUES ('foo','bar'),('baz','foo')) TempTable(Field1,Field2)
 
-- Returns 1 row with 1 checksum column
SELECT CHECKSUM_AGG(CHECKSUM(Field1,Field2))
FROM (VALUES ('foo','bar'),('baz','foo')) TempTable(Field1,Field2)

Regression testing

These help with a common problem: when you’re refactoring a database object, how can you be sure that you haven’t changed the existing functionality? Sometimes it’s enough to spot check a few inputs, but often the logic is complex enough that this does not provide a high level of confidence. With CHECKSUM and CHECKSUM_AGG, you can quickly check large numbers of test cases.

For example, say we have a TVF called MyDateTVF that takes in a date parameter and returns columns Column1 and Column2. I want to refactor this function and then test that the functionality is unchanged for every date in 2018. If we have a table called DateList which contains every date (more useful than you might expect in a DB with a lot of temporal aspects), I can simply run the following before and after my change:

SELECT CHECKSUM_AGG(CHECKSUM(MDT.Column1, MDT.Column2))
FROM DateList DL
CROSS APPLY (
    SELECT Column1, Column2 from dbo.MyDateTVF(DL.Date)
) MDT
WHERE DL.Date BETWEEN '2018-01-01' AND '2018-12-31'

If that query returns the same checksum before and after my change, we can rule out any regressions for those inputs. Nice and easy!

Tailwind CSS

Web styles designed from scratch

I recently overhauled the UI for my letter builder web app, switching from Bootstrap to a neat framework named Tailwind CSS. It’s been great so far.

I dabble in web development, but it’s not “my thing”. Most of my time is spent on back-end systems and the occasional native UI. When I’m building a web UI, I usually spend a lot of time on MDN or W3Schools looking up syntax details.

Tailwind

Enter Tailwind. It’s a utility-first CSS framework, which in practice means they give you a whole bunch of “utility” classes which are effectively aliases for common styles. Here’s an example from when I was styling a button:

<button class="bg-blue-dark text-sm text-white rounded py-2 px-4 my-2"/>

With these classes, I’m saying that I want a dark blue background, small white text, 2 units of padding on the top and bottom (py-2), 4 units of padding on the left and right (px-4), 2 units of margin on the top and bottom (my-2), and rounded corners. Whew!

Right away, we can notice a few advantages relative to the normal way of doing things:

  1. This is fast to iterate on. I can add another utility class in-line without digging through my CSS file and reasoning about selectors.
  2. The class names are concise yet informative. py-2 is clearly operating on the Y axis (top and bottom), which is much easier to remember than a padding style with multiple unlabeled values.
  3. I have fewer choices to make. I didn’t need to worry about whether to use #0033CC or #0000FF for a dark blue, I just asked for dark blue. Same thing with padding+margins, I just chose from a small set of integers instead of wondering whether to do 0.5rem or 0.6rem.

Isn’t putting all your styles inline just asking for trouble?

Yes, this can get out of hand if you put too much stying inline – but Tailwind utility classes can be extracted into components as soon as you need some additional abstraction. The authors even recommend that:

Tailwind encourages a “utility-first” workflow, where new designs are initially implemented using only utility classes to avoid premature abstraction.

While we strongly believe you can get a lot further with just utilities than you might initially expect, we don’t believe that a dogmatic utility-only approach is the best way to write CSS.

Curation VS organic growth

I’m being a little hard on the “usual” way of writing styles in CSS. The web grew more-or-less organically, so it’s not fair to expect an overall design from the mess of styles available to modern browsers. Thankfully, that’s where projects like Tailwind come in.

It’s remarkable how much nicer it is to build web UIs when working with a thoughtfully curated and documented subset of styles. Sometimes a big step forward doesn’t need to come from a clever technical breakthrough – simply organizing existing information+symbols in a better way can reap massive benefits.

Pulumi for Cloud Infrastructure Management

IaC, but for real this time

I’ve recently been playing around with some cloud development tooling by a startup named Pulumi, and I thought I’d write up my first impressions.

Pulumi can be summed up as “Infrastructure as Code – but really, we mean it this time.” Instead of mucking around with YAML files and proprietary syntax, you define the infrastructure you need in actual code (JavaScript or Python, with more languages coming later). Is your production environment slightly different from your test environment? No problem, that’s just an if statement (or a more complex abstraction) away.

It’s still very early days (as of this writing, Pulumi is on version 0.14.3), but the general approach shows a ton of promise.

The State of Serverless

Almost, but not quite there yet

In my spare time I have been mucking around with 2 big Functions-as-a-Service (FaaS) offerings, AWS Lambda and Azure Functions. I’ve been meaning to write up a “The state of serverless development” post, but today Mike Roberts updated his overview of the market for serverless computing and it’s far more thorough than I could ever be.

The whole thing is well worth a read if you’re interested in the area, but these parts (emphasis mine) really resonated with me:

Serverless is not the correct approach for every problem, so be wary of anyone who says it will replace all of your existing architectures. Be careful if you take the plunge into Serverless systems now, especially in the FaaS realm. While there are riches — of scaling and saved deployment effort — to be plundered, there also be dragons — of debugging and monitoring — lurking right around the next corner.

Serverless services, and our understanding of how to use them, are today (May 2018) in the “slightly awkward teenage years” of maturity. There will be many advances in the field over the coming years, and it will be fascinating to see how Serverless fits into our architectural toolkit.

This is exactly right in my experience.

Lambda and Azure Functions let you write+deploy code quickly without an infrastructure team and an execution platform. However, the developer experience is often a big step backwards – Lambda doesn’t offer any remote debugging support, and just running+debugging functions locally is a big pain. Azure is further ahead in debugging, but things are still more complicated and less reliable than when debugging traditional apps. Integration testing is difficult on both platforms.

headshot

Cities & Code

Top Categories

View all categories