Designgineering Chronicles: Months 6.5-8.5, Part 1

It’s a month later than I would have liked, but at long last an update on project Cantaloupe which is full steam ahead on development. What’s it like to build and use a design system at the same time? In Part 1, we talk workflow, CSS utilities, and houses of cards.

Scribbles turning into ordered lines

I started writing this on a flight from LA to NYC about 10 days ago. There was 1h 45m remaining on the flight and I truly thought I would be able to just write then publish and it will be done! That’s mostly how I’ve done these posts so far, but this one was a little rant-y and required follow up.

You’ll also notice that this is Part 1 – Part 2 will contain more technical notes and code snippets. I am extremely hungry right now and need to finish this, so Part 2 be published tomorrow-ish (and I did that, here is part 2!).

Quick recap

Let me give a quick recap of the last Designgineering Chronicles / what this series is about: I started working as a Design Engineer at Penske Media Corporation 8.5 months ago. As soon as I started (or, perhaps, as soon as after my interviews), I thought, PMC needs a design system. This series has become my documenting exactly how one goes from that thought to an actual design system. We aren’t there yet.

In the last Chronicle, I wrote about Cantaloupe, the code-name for a redesign of one of PMC’s larger properties. We are doing the redesign internally (which is possibly a first for PMC) and I am leading the front-end. While the primary goal of the Cantaloupe project is to launch a redesigned site, the secondary goal is to build out as much of a design system as we can in conjunction with the redesign.

Build the design system as you are using it! What could go wrong?

Credit to my co-worker, Jorbin, for posting this image to our #engineering channel.

It’s not as bad as that photo indicates, and I don’t think it will get that bad, but a couple of weeks ago we were a little worried. Now that Cantaloupe’s development has been full steam ahead for about two months, the fun planning, tool building, and discovery stages that were the contents of the last Chronicle post are over, and we need to get the thing done.

A personal note

In general, my tone throughout this series (and probably in most of my blog posts) is, at least I think, very positive and enthusiastic, and that’s how I feel a lot of the time, but let it be known that there are low points. I question the choices I’ve made, worry if I’m over-complicating things for others, and worry that I’m slowing down the project, that my fixation with CSS and the system will cause a missed deadline with impacts much more dire than a bit of smelly CSS.

But then I remember that I’m working on a team, and a team of folks with a lot more experience at PMC than I have. Everyone is 100% aware of the project’s status, and as I’ve mentioned before, project management at PMC is a force to be reckoned with. If my attention to detail became problem, it would be addressed well before a missed deadline. I have many positive things to say about my job, and that’s one of them.

So, I just wanted you to know, reader, that in case it sounds like what I do is all fun and smooth sailing and exciting and that my life is perfect – that’s what I sometimes think when I read people’s blog posts – I want you to know that it’s not like that. Sometimes work is really hard and frustrating or just boring. But then, something will happen that reverses my negative perspectives, and I’ll be back to my usual happy, CSS-loving self, always on the lookout for making things better.

Okay, onto the Chronicle!

Workflow woes

To review the developers that are on this project: there’s me, leading front-end, AS, who is the main tech lead and back-end lead, and two contractors from an agency we work with in India, one focused on front-end and one on back-end.

At this point, we have closed out our fifth development sprint. I know, because I’ve been keeping a ticket with “Running List of Design System To-Dos” a.k.a. “Tech-debt we better fix later plus ideas and other stuff”.

Full-stack fallacy (probably sometimes)

In terms of splitting up front- and back-end work, we started by trying out a workflow where any given feature story/ticket goes through different swim lanes – e.g. the “Author” component is in a front-end lane, then it gets assigned to a back-end developer and moved to the back-end lane. After the first sprint or sprint and a half, this proved to be too involved. It was unclear who was waiting on what and how the pull request flow should go (do we have a feature branch, then FE and BE branches off of that, then merge those into the feature branch, then into master??).

We decided to go back to PMC’s usual, full-stack, approach where one person takes ownership of a given feature. I mean, the front-end developers can write PHP and the back-end developers can write CSS, and this is what we do on the business-as-usual teams at PMC. What could go wrong? That also did not work.

Here’s a non-committal opinion: Full-stack development is probably sometimes a fallacy, and the consequenses will probably usually be felt on the front-end. This opinion has been echoed throughout the Twitter-verse and in pointed articles over the past year, and I must say, it does align with my experience.

For Cantaloupe specifically, the front-end knowledge required to use the system in its current state is specialized. You can’t “just write the CSS” for a ticket, you have to understand the architecture. At the end of the day, when you are working under a deadline, it’s an inefficient use of time for a developer with the specialized knowledge to do things the developers without the specialized knowledge can do, and vice-versa.

Take me, for example. I have the specialized knowledge for the system. I can also write PHP, but it takes me a lot longer to write PHP classes and unit tests than it does to build out patterns in the system. And it takes AS, the back-end lead, a lot longer to build out patterns than to write PHP. And time spent reviewing and going back and forth over pull requests increases accordingly. Not good.

For example, I got a pull request where a back-end developer had written 100+ lines of CSS in the old way (with nested BEM selectors, hard coded pixel values, heights and widths galore). They had completely ignored (or not noticed…) the output from stylelint I had put so much thought and care into configuring. Dark times, indeed.

Back on track

At the time I started this post, 10 days ago if you remember from above, we were not-that-behind-but-a-little-behind and were discussing plan B. What should we do to speed up development? Bring on another contractor, ditch the system and write CSS in the old way so that the back-end developers can more easily contribute? I think I would have a mental breakdown if I had to review those pull requests. No, the answer is that each of us should work on what we’re best at!

So now, about two weeks after my initial shit-fit about the ignored linter rules…things are looking up in a big way!

The key has been to informally split up the front- and back-end tasks instead of planning it out ahead of time and tracking it in JIRA. Our workflow, now, goes something like this:

  1. Front-end dev takes the “Video player” ticket
  2. Front-end dev builds out the interface with the system
  3. Front-end dev stubs the data object in the PHP template and pings the project channel/back-end developers with something like “Video player ready for back-end”
  4. Back-end dev takes over, writes any new PHP classes and unit tests and adds real data in place of the stubbed data

It could also go vice-versa, where the back-end developer starts a ticket but, I think, it seems to go more smoothly when a front-end developer starts the feature. That way, the markup is in Twig and therefore in the pattern library, up to standard from the get-go – otherwise, since the back-end folks are less efficient working in patterns, they will write HTML in the PHP templates (the traditional way). Then, there will either be redundant work for the front-end person to get the markup into the Twig / the pattern library from PHP, or the feature will be a one-off, outside of the system.

There is definitely a workflow where front- and back-end can happen at the same time, but the system – specifically naming – needs to mature some more before we are ready for that.

Anyway…it’s a process, and we are learning. I think it’s especially hard with WordPress theme development because the division between front-end and back-end is not as clear as it is with other frameworks. I’d be very curious to learn how agencies like XWP and Human Made do this – do the front-end developers build out a static site, then hand off the whole thing to back-end folks to divvy up into template parts? Do they have a specific ticketing workflow? Or do they really do full-stack development? I’ll need to ask them one of these days.

I love utilities! I hate love utilities!

The way the system has come together is very different from how we have written CSS on other projects, mostly in that we are fully committed to utility-driven CSS. That means writing out a lot more class names and a lot less CSS. This is a big change from how PMC (and I) have written CSS before. In fact, just last year, I was extremely skeptical about atomic CSS / utility CSS. Now, I’m singing a very different tune.

I used to think utilities meant removing the “purity” of writing clean, semantic CSS – how it should be! I thought utilities were lazy. I thought utility-driven, or “atomic CSS” removed the craft from writing CSS, making it easier for a developer to brute force their way into a solution.

Now, I see it completely opposite!

I think utilities make it more difficult to write smelly CSS by providing good friction. I will try to explain.

Stray declarations are more noticeable

When using utilities – specifically ours since they have very verbose naming e.g. pmc-u-font-size-42@desktop-xl – you need to know exactly what you are trying to do. Leaving stray declarations around is a lot more noticeable because you already want to limit the amount of classes you add, lest your eyes bleed (it can be a lot of classes and hard to read at a glance).

Utilities don’t exist for brute-force styling

If you are trying to do a weird positioning thing – e.g. using absolute positioning and hard-coded values for something in a corner instead of a flex approach – you, um, can’t do that because the utilities don’t exist for it.

If the Invision screen shows a font-size that is 1px off from what the utilities that already exist, it is easier to round to the existing font-size and in all likelihood no one will notice.

If a developer is tempted to write an isolated (min-width and max-width) breakpoint, they will be have to figure out the min-width solution because utilities don’t exist for the isolated one.

Stylesheets stop growing, mostly

At this point in Cantaloupe, our common.css stylesheet (which contains primitive pattern styles and utilities) is 50kb, almost 9kb gzipped (and would be > 8kb if we didn’t have copy-pasta from another project for a certain feature but whatever). We are probably 70% though UI development, and most pull requests at this point contain a maximum of 5 or six new lines of CSS for styles that just don’t fit into algorithms (more on that in Part 2) and utilities for whatever reason.

In fact, it is very common for a pull request with a new feature to contain zero new CSS (!!!!) and, apart from structural wrappers, zero new HTML (!!!) because we have a few useful markup patterns nailed down in the pattern library. When this started happening over the last couple of weeks, I was like… worth it!!!

Reviewing pull requests is faster once your eyes adjust

Since I have a good vocabulary for our utilities at this point, when I review pull requests I can see immediately, in a single file, what the CSS programming is – I don’t have to cross reference a stylesheet with a template and visualize what is attached to what. It’s right there, all together. This can be a bit of a pain when working in the Inspector, but both Chrome and Firefox have a nice interface for toggling class names:

Firefox developer tools for toggling utility classes.

And, once you are used to the naming, you can bang out interface code really, really fast. There’s no jumping between files, your text editor can autocomplete the class names (I haven’t actually set mine up to do this), and, um, that’s all I can think of that is faster.

You have to name a lot less things

And naming things is very hard, as you might be aware, and this is amplified on teams where English isn’t everyone’s first language.

In our system, you only need to give an element a name if it needs non-utility styling or if the name in the initial ticket is not sufficient, which, I’m very happy to say, is rare. At this point in the project, if you wrote new CSS, you probably missed something.

…but there are downsides

On one hand I’m like…muhahahahaahah now we can find out who really knows CSS, and if they don’t, they have to learn it in order to use the utilities!!!

But then, during the dark times, I was like, F#CK…the back-end developers don’t know CSS that well and the project has to get done and, at the end of the day, does it really matter if it’s done with positioning vs. flex if it works?!

Sheesh.

And debugging utilties…if there is a Really Weird Thing™ going on, I definitely find a long string of class names harder to debug than a declaration block.

But I must say, when I build out a feature that fits in perfectly with the utilities we have so far, I’m like, this is bliss! Or when I review a PR from the front-end contractor, and I get a full picture of what’s happening from looking at a single chunk of markup because he built out an entire new feature with existing patterns…bliss! Are utilities are “The One True Way”? Isn’t the goal to stop writing new front-end code?

And then…the next day, I will feel queasy about how many bytes are being added to the HTML because of all these class names. Is it better to have that weight as CSS, perhaps as mixins? Is passing strings of classes to PHP templates slowing down the server response? How would we figure that out and what would we do? Find and replace pmc-u-background-brand-red-dark:hover with u-bgbrd:h, and rip out the reusable configuration and includes in favor of hard-coded markup?

This is my nightmare, but I don’t think it will be an issue, and I have heard from reliable sources that compression these days is good enough that it won’t be a problem. I will sleep easy…tonight.

I love CSS but I am going to rant about it for a second

CSS is really freakin’ hard. Well, maybe it’s not that hard if you understand it. The thing is, I love CSS so much and think it’s the coolest thing ever and I want more people to feel that way, but the time and energy I’ve put into actually understanding CSS is a lot to ask of someone who has 18+ higher priority things to do. It’s totally different from any other programming language; it’s domain-specific, it’s specialized. If a developer doesn’t understand the domain – that is, the browser and rendering, the box model – they don’t understand CSS. And, to a large extent, that domain knowledge applies only HTML and CSS.

Also unlike other programming languages, someone can write the smelliest CSS with little understanding of what they wrote…but their code will work! This is at once the most beautiful and terrible thing about HTML and CSS when it comes to working on teams.

Houses of cards

Here is a small story that basically the story in the beginning of this talk by Brad Frost but in my own words.

In late 2016, Developer A built a teetering house of cards (here us an explanation of that idiom) with HTML and CSS, but it passed the product review, so all was well. That is, until early 2018 when Developer B was tasked with adding Very Important Feature to the house of cards. Developer A has since left the company, but they wouldn’t be able to tell Developer B what was going on even if they were still here – such is the nature of a house of cards.

As Developer B starts on Very Important Feature, the house of cards collapses. Developer B now resents both CSS and Developer A, and delivery of Very Important Feature is now postponed. Eventually, Developer B is able to reconstruct the teetering house of cards enough to pass product review.

Six months later, Developer C is tasked with updating Very Important Feature according to new information acquired in A/B tests. The house of cards, again, collapses but Developer B, who initially built it, is on a different project and wouldn’t remember how the thing worked anyway. The company is now budgeting for hundreds of thousands of dollars to go into a redesign to build a potentially more resilient foundation for future houses of cards.

Building a design systems means you STOP BUILDING HOUSES OF CARDS, and that requires specialized knowledge. Not everyone can write CSS for a design system, and not every one needs to. There are developers with the skills to build the design system, and there are developers with other skills, who will use the design system. In all likelihood, these are different people.

I think the stress points during the dark times with Cantaloupe a couple of weeks ago were are result of the same developers building and using the system at the same time. Shocker!

Stay tuned for Part 2!

Once again, this is a long blog post and I am hungry! So, there is a part 2 that I am almost finished with that contains more technical notes and code snippets. Stay tuned! Good job staying tuned, Part 2 is finished!

Also, side note – I took a bus from NYC to Pittsburgh yesterday (which is like 8 hours…I don’t necessarily recommend it but it’s fine) and we stopped at a truck stop for bathroom and snacks. I was initially excited to buy gross gas station snacks, but for some reason I had such a craving for…

My hand holding a container of cantaloupe pieces