Factory Functions: All About Interfacing
Tags: javascript, webdev, beginners, gamedev
Published: 2021-10-31 17:25:38

In the last couple posts, we looked at:
* [Rethinking Gameboards](https://dev.to/parenttobias/rethinking-gameboards-3cin): looking at the CSS driving a chess board, and 
* [Chess Pieces, Inheritance vs Composition](https://dev.to/parenttobias/chess-pieces-inheritance-vs-composition-52j2): Building pieces by *composing* them of functionality, being able to plug-and-play parts as we need.

In this one, we will revisit the gameboard itself, but we'll look at the javascript this time. The [replit](https://replit.com/@TobiasParent/BonyEvilSquares#script.js) contains a working chess board, but it leaves something to be desired. this post will address the what, why and how of that refactoring and rewrite.

## The Why
The gameboard doesn't require much for functionality. In the current version, we can `add()` pieces to the board, and then the board itself handles the moves. Works, and it works pretty well. But it isn't really a *functional* solution. It isn't a great interface.

When we talk about interfaces, we mean "How we communicate to and from this thing." We want a mechanism to tell an object or component something, and we would like a mechanism to let that thing tell us something in return. The javascript engine itself, right in your browser, includes some objects with well-defined interfaces. Some examples:

```js
// the Math object contains a number of useful interface methods!
// Math.random() is an interface method that tells us something...
const someValue = Math.random();
const someOtherValue = Math.random();
// Math.min() is another one: we tell it any number of values,
//  and it tells us something about them.
const minValue = Math.min( someValue, someOtherValue );

// the Date object is another. We can pass data in and
//  get data back, or we can simply ask for data without
//  passing anything in.
const rightNow = Date.now();
``` 

Interface methods are all about *communication*. We want to hide all the implementation details for our object or component inside the thing so we don't have to get dirty with it, but then we want to be able to communicate with that implementation, still without getting dirty. We do so by providing a means of getting in there.

So in the case of the `Queen`, for example, here's the entire code:

```js
const Queen = (...classNames) => (starting) => {
  let current = starting;
  let hasMoved=false;
  const piece = Piece(starting);
  const domNode = piece.domEl();
  domNode.classList.add("queen",...classNames)

  const isValidMove = (target) =>{
    const [start, end] = [Piece.toXY(current), Piece.toXY(target)];

    return moves.diagonal(current)(target)
        || moves.lateral(current)(target);
  }

  const to = (target)=>{
    if(isValidMove(target)){
      hasMoved=true;
      current = target;
      piece.to(target)
    } else {
      console.log("Nope nope nope!")
    }
  }

  const domEl = () => piece.domEl()

  // The returned object defines the interface!
  return {
    to,
    isValidMove,
    domEl
  }
}
```
Everything within the queen is hidden away. We don't have to explicitly tell her *how* to move, we simply say `.to("C3")` and she knows to check if its valid, and to make the move. The *implementation* is internalized, the *interface* is externalized. In this case, it's three exposed methods: `to`, `isValidMove` and `domEl`. We don't know *how* the Queen does them, we just tell her something (in the first two cases), and if needed, we get a reply (in the last two cases).

But in the case of the `Gameboard`, the exposed interface is this:

```js
const Chessboard = function(domNode) {
  const cols = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'];
  let selected;
  let pieces = [];

  const getSquareSize = (board) => {
    // internal functionality, commented out for brevity
  }
  domNode.addEventListener("click", (event) => {
    // commented out for brevity
  })

  const add = (piece) => {
    pieces = [...pieces, piece]
    domNode.appendChild(piece.domEl() );
  }

  return {
    add
  }
}
``` 
So the exposed interface is one method, `.add()`. And to me, that is kind of... limited. I would like to make this a little more useful, really. It would be nice to make this something we can play from the console or commandline, for example, or to be able to read in a text file containing an entire game and play it out move-by-move. But to do that, we would need to tell the board "Hey! This piece here? Move it there." Or "Hey, when we move this piece there, and it captures that piece? Remove that piece."

We need to improve the interface.

## The What
What might be a useful interface for a Gameboard? I can think of a couple methods might be handy, so let's start there:

```js
const Gameboard = (domNode) => {
  // let's leave implementation out for a minute, and focus
  //  on what our interface might be:
  return {
    at: {
      // at is a nested interface, providing us with some
      //  drill-down functionality:
      place: /* lets us put something on the board */,
      remove: /* removes something from the board */,
      get: /* Just gimme the piece if there is one */
    },
    from: {
      // this might also have a nested interface, so we can
      //  communicate in a declarative way:
      to: /* lets us move from one location to another */
    },
    board: {
      // again, another nested interface?
      toString: /* return a JSON object maybe? */,
      toDOM: /* Could return a reference to the board's DOM? */
    }
  }
}
```

So I'm not worrying about the *implementation* yet. I don't know how we'll be doing this stuff internally, I'm simply building my "wish-list" interface. With that, it would be easy to communicate with the board:

```js
// Putting something on the board...
myChessboard.at("C1").place(Bishop("black","queens") );

// and moving that?
myChessboard.from("C1").to("F4");

// We can remove pieces explicitly, if we like:
if(myChessboard.at("F4").get()!==null){
  myChessboard.at("F4").remove();
}
```

So an interface like that is a bit more expressive, but how might we implement that?

## The How
Creating the interface is not much more difficult than planning it out, though it still requires some planning and forethought. For example, in the new mechanism of `.at(...).place(...)` we are using the cell as the "key" of our piece, as only one thing can be at that cell. In the older version, we did this:

```js
chessboard.add(Rook("black", "kings")("H1"))
```
With that, the board is unaware of what is where. The piece knows where it sits, but the board doesn't know *what* it contains. 

With the new version, we do this:

```js
chessboard.at("C1").place(Bishop("black", "queens") );
```
Now the chessboard is aware that it contains cells, and it handles creating and placing that piece on that cell. So where before our `Chessboard` internally had an array of pieces that was simply the piece, we need to change that some. Now, it needs to keep track of both the piece, *and its location*. So that changes the **state** of that array of pieces to something more like:

```js
let pieces = [
  {
    piece: Rook("black", "queens"),
    location: "A1"
  },
  {
    piece: Knight("black", "queens"),
    location: "B1"
  }
  // and so on
]
```
It isn't a huge change, and so far as anything **outside** the chessboard knows, it isn't significant. The pieces themselves still work in the same way, and while the way we communicate with the board has changed, it isn't bad. Lets take a look at the implementation of the `.at(cell)` functionality:

```js
const at = (cell) => {
  // placing a piece takes two steps:
  //  add the piece to the array as an object, and
  //  tell the piece itself which grid-area to use.
  const place = (piece) => {
    const addMe = {
      location:cell,
      piece:piece(cell)
    }
    pieces = [...pieces, addMe];
    domNode.appendChild(addMe.piece.domEl())
  }
  // removing a piece is simply removing the one with
  //  a `cell` property that matches.
  const remove = () => {
    const item= pieces.find( piece = piece.location===cell);
    // pull it out of the DOM...
    item.piece.remove();
    // and out of the array.
    pieces = pieces.filter(piece => piece !== item);
  }

  // Now, the sub-interface!
  return {
    place,
    remove,
    get value(){
      return pieces.find(piece=>piece.location===cell).piece;
    }
  }
}
```
So, when we `.at(cell).place(piece)`, we are doing two things: first, we add an object to the array using the format we've standardized, and second, we add the piece to the DOM within the gameboard.

When we remove the piece from the board, we reverse that. We remove that particular node from the DOM, and then we tell the array to filter for only those pieces that are *not* the one we wish removed.

Finally, we want a getter for the `value` of the given cell. The value is not the entire object but solely the piece within that object.Note that here, I did change the interface a little: `get` is a keyword in javascript, and I didn't want to cause confusion.

We can do much the same for the `.from(starting).to(ending)` functionality, creating another interface for it. Something like this:

```js
const from = (starting) => {
  const to = (ending) => {
    // Lets simply map over the pieces array, and update
    //  the appropriate one.
    pieces = pieces.map( (item) => {
      if (item.location===starting){
        item.piece.to(ending);
        // we'll return a new object for the moved piece
        return {
          piece: item.piece,
          location: ending
        }
      } else {
        // we simply pass along the object for the rest.
        return item;
      }
    })
  }
  // and remember to return the interface itself!
  return {
    to
  }
}
```

So those two will let us do things like this:

```js
chessboard.at("A1").place(Rook("black", "queens"))
chessboard.at("B1").place(Knight("black", "queens"))
chessboard.at("C1").place(Bishop("black", "queens"))
chessboard.at("D1").place(Queen("black"))
chessboard.at("E1").place(King("black"))
chessboard.at("F1").place(Bishop("black", "kings"))
chessboard.at("G1").place(Knight("black", "kings"))
chessboard.at("H1").place(Rook("black", "kings"))
chessboard.at("A8").place(Rook("white", "queens"))
chessboard.at("B8").place(Knight("white", "queens"))
chessboard.at("C8").place(Bishop("white", "queens"))
chessboard.at("D8").place(Queen("white"))
chessboard.at("E8").place(King("white"))
chessboard.at("F8").place(Bishop("white", "kings"))
chessboard.at("G8").place(Knight("white", "kings"))
chessboard.at("H8").place(Rook("white", "kings"))

// Let's try moving one by code now!
chessboard.from("H8").to("H4");
```

With this, the state of pieces and their locations is being maintained in the board, and the board notifies the piece to update its CSS as needed. With that, we have a more useful and extensible `Gameboard`!

## The Recap
Interfaces are powerful, and fundamental to good OOP. The three principles that are foundational to OOP are *encapsulation* (we hide stuff), *communication* (we provide a way to talk to stuff) and *late instantiation* (we can make new stuff as we need, at runtime). And in our `Piece` and `Gameboard`, we have built a good solid base on those three principles.

To see this one in action, here's [another replit](https://replit.com/@TobiasParent/betterChessboardInterface). I have made one other change to that replit that wasn't in the other: the `chessboard` is defined on the global `window` object. This is *not* a thing done in production, but what that does *here* is... you can test moving a piece by typing our interface methods directly in the console as well as using the GUI!