Tytr

A code blog

👁‍🗨❤️👨🏻‍💻

Roadmap Index

3/6/2022

What's in an application

This is something I really like talking about with my students.

It can also be a frustrating experience for me, because I know these high level concepts are counterintuitive and difficult to fully digest.

The general ability to take a complicated topic and distill it into a simple and deliverable chunk of information is already a challenge.

Couple that with the difficulty of most listeners and readers to expand that idea back out into usable information as part of their mindset...it can be disheartening.

Still, this type of distillation is the greatest bang for your buck value that I can give you for your reading time.

Information Systems

All applications are based on information. There is some input of information, there is some process that transforms that information into viewable content.

That's really all it boils down to.

Data -> Process -> View

Examples

Here are a couple quick examples to help get the idea across. Let's say we have an array that represents the state of our tic tac toe board.

let board = [
    "", "", "",
    "", "", "",
    "", "", "",
];

// Or with some values after a few turns:
let board = [
    "X", "O", "",
    "X", "", "",
    "", "", "O",
];

This array is that data/state of our application. Now we need some process that can transform this into viewable information.

There are infinitely many processes we can write to transform this data into infinitely many views. Let's see a couple of interesting options.

Let's say an engineer wants to view the data to understand the current state. The dreaded console.log statement:

console.log(board);

This is a process that emits a view! It takes in some data, does something with that data, and then spits out something for us to see! In this case the view is being generated in the console for the programmer to see.

Data -> Process -> View Array -> console.log -> Data viewable in console

Now let's see how we might transform this data into a string of HTML.

function generateCellHtml(value) {
    return `<div class="cell">${value}</div>`;
}

const cellHtml = board.map(generateCellHtml);
const htmlString = `<div class="board">${cellHtml}</div>`;

document.body.innerHTML = htmlString;

Data -> Process -> View Game board array -> html generation -> viewable in browser

There's some nuance missing in the above example. If I actually wanted to do this I would probably also include some logic to add .rows for each "row" in the game board.

Note: What's crazy is you can view your own source code this way! Data -> Process -> View Thoughts -> Typing in text editor -> Source Code Your source code is a view into your thoughts about the program! Take this a step further and you can realize that using a different set of tools or programming language is really just switching out the P bit in our D -> P -> V analogy

State

State is the one of the most crucial parts of an application. Getting it wrong can make your life many times harder than it needs to be.

Getting it right will not only make maintaining your application easier, it will enable you to build features that would other be challenging.

One of the early goals of the Tic Tac Toe project is having students make a bunch of mistakes with how they think about and store the state in their application. In fact I specifically avoid mentioning the word state when introducing them to the web platform and getting them started on the project.

It's good for students to first face the issues of having mangled state so that they can see how much easier life would have been if they had first been disciplined about their state.

The naive approach to getting tic tac toe up and running is to just mutate the actual HTML and let that act as both your view AND your state:

function getCells() {
    return document.querySelectorAll('.cell');
}

function cellOnClick(event) {
    // Hardcode X for now
    event.target.innerHTML = 'X';
}

window.onload = function() {
    const cells = getCells();
    
    for (const cell of cells) {
        cell.addEventListener('click', cellOnClick);
    }
}

The above will get you to the point where you are setting cells to X on click. Not bad, but how can we go about checking for a winner now?

Well, the only information we have right now is the actual value of the innerHTML property of each cell...yikes

const cells = getCells();
const board = cells.map(cell => cell.innerHTML);

// board will be an array of 9 elements, like:
// [ "", "X", "", "O", "", "O", "", "", "" ]

So you have to look to the HTML to be your state. Technically you can make this work, but it has a couple of nasty properties.

By coupling your state to your view you lose a lot of control. How would you go about writing a test to cover your win condition logic? I can actually think of a way to do this, but rather than solve that problem, let's see if we can decouple our state from our view instead.

State -> Process -> View

We have this little D/S -> P -> V analogy, let's keep going with that. We already discussed what the D/S part of this might look like, but let's recap really quick.

That data for our tic tac toe game is just the board itself.

let board = [
    "", "", "",
    "", "", "",
    "", "", "",
];

Great. Now what about the process bit? Well, we could follow the earlier example and actually build a string of HTML. That's honestly trash and I would never want to hand roll a bunch of HTML generation code. Just use a component framework.

For now I think a good middle ground is to put the cells in the HTML and just update their values based on the state. Like this:

function renderBoard(board) {
    const cells = getCells();

    for (const [cell, index] of cells) {
        // This is the fun bit
        cell.innerHTML = board[index];
    }
}

Above we are mapping that values in our board array to the cells based on the index of the cell. More importantly, by encapsulating that logic in a function that depends only on the board, we can easily replace it with something more complicated later.

Conclusion

Hopefully you're starting to see how we can pull the state out of our HTML and take back control. In the next article I'll take you to the finish line and show you exactly how I would structure the state for my version.

I'll include a github link at the end so you can take a look at all my code.



Ask me questions on twitter or email me at ty@tytr.dev