DEV Community

loading...
Cover image for Get Hired: Handling Object-Oriented Design Questions

Get Hired: Handling Object-Oriented Design Questions

techdebtor profile image sam ・9 min read

So I did something terrifying last week: I did a technical interview on camera. 🙈 Lusen from Candidate Planet asked me an object-oriented design question and we whiteboarded a solution. Check out the video here! ✨ This post will go over the same question as the video, but in more depth and will also include the code solution in Java.

So why did I agree to be filmed doing something that I have nightmares about? Well, I thought about what my goals with this blog series were. I started it after a quick, intense job search where I had to learn from my mistakes, fast. I've worked hard, but I also have to acknowledge the immense amount of privilege that I have. I grew up in a white, upper middle class family with an electrical engineer for a father. I started coding when I was 9 and I went to a top 10 university for computer science. The deck was stacked in my favor. But it shouldn't be this hard to get into the tech industry. There are so many artificial barriers to entry that exclude anyone from a background not exactly like mine. And it's bullshit. It's alpha male bullshit. And I'm tired of it. So I need to make my content as accessible as possible - hence the video. I'm willing to try other formats if people want to see those too. Which means there may be more videos on the horizon - let me know what you'd like to see in the comments 👀

Now let's dig into the topic: object-oriented design questions!

The Object-Oriented Design Question

The object-oriented design (OOD) question is centered around writing out a program to model a real-world system. For example, one OOD question I've been asked was to design a restaurant. The solution would involve specifying the important classes and methods for managing a restaurant. Examples of functionality to include would be how to manage the menu, kitchen inventory, seating arrangements, and reservations. You would also want to model the actors in the system, which in this case would mean restaurant staff and guests.

One tricky thing to look out for is that OOD interview questions often sound similar to system design questions. The difference is in scope - with a system design question, you're being asked to design a system end-to-end, meaning front end, back end, and infrastructure. With an OOD question, you're being asked to zoom in on one piece. If you're not sure, you can always ask your interviewer to clarify.

Concepts to Know

Before you walk into an OOD interview, you should have experience designing and implementing classes, as well as a working knowledge of the four principles of object-oriented design. To give you a refresher, they are:

Encapsulation

Encapsulation means restricting access to data with public and private classes and methods. This often looks like using getters and setters to access private variables inside a public class:

public class Chair {
  private int numLegs; 

  public int getNumLegs() {
    return numLegs;
  } 

  public void setNumLegs(int newNumLegs);
    numLegs = newNumLegs;
  }

Abstraction

Abstraction means having information tied to the model of something rather than the instance of it. In practice, this can look like a class interface that subclasses implement:

public interface Furniture {
  public void useFurniture();
}

public class Chair implements Furniture {
  private boolean occupied;

  public void useFurniture() {
    sit();
  }

  private void sit() {
    occupied = true;
  }
} 

Polymorphism

Polymorphism means that an object can take many forms. A piece of furniture could be a chair, a table, or a bed. Any code written for the parent will also work for the children.

public class Furniture {
  private boolean isInUse;

  public void useFurniture() {
    isInUse = true;
  }
}

public class Chair extends Furniture {
  public void sit() {
    useFurniture();
  }
}

public class Bed extends Furniture {
  public void sleep() {
    useFurniture();
  }
}

Inheritance

Inheritance means an object has an "is a" relationship with another object. For example, an armchair "is a" chair. This can look like a subclass reusing code from its parent class:

public class Chair {
  private int numLegs; 

  public Chair() {
    numLegs = 4;
  }
}

public class ArmChair extends Chair {
  private int numArms;

  public ArmChair() {
    super(); //this calls Chair's constructor and sets numLegs to 4
    numArms = 2;
  }
}

More senior candidates should also be familiar with common design patterns. These include:

Constructor Patterns

Some common constructor patterns are factories, builders, and singletons. Builders can be useful in interviews because they make constructors with long argument lists more readable.

Structural Patterns

Structural patterns determine class composition. Two major structural patterns are facades and wrappers. Personally, I haven't seen interviewers dig too deeply into this area. OOD questions usually have a straightforward solution, so the class structures are typically pretty simple.

Behavioral Patterns

Behavioral patterns determine how classes communicate. An important concept here is the chain of responsibility - requests should be handled by going through a sequential chain of handlers so you're guaranteed to always go through all the handlers and process the request in the same order. Another behavioral pattern to know is the observer pattern, where an object listens in for changes coming from another object.

More resources about these patterns below 👇

Let's Walk Through An Interview

We're going to work through a question that a major tech company asked me in a phone interview. The question is, "Design a program to solve a jigsaw puzzle."

In my interview with Lusen, I diagrammed the solution on a whiteboard. This post has the code solution, but you might notice it's not functional code. That's because a lot of it is written with abbreviated syntax, which is a liberty you can take in this form of interview. Nobody is going to compile your code, so feel free to abbreviate things.

Clarifying Questions

The first thing you should always do is ask questions to clarify the problem. What does a jigsaw piece look like? In this case, all pieces will have four sides that can either have an indentation, an extrusion, or a flat edge:

Three puzzle pieces

A few more things to clarify: What does the board look like? We'll say that our board is a rectangle. How do we know two pieces fit together? The curvature of the indentation on one piece will match up to the curvature of the extrusion on another. And finally, can one piece fit with multiple pieces? No, the matches will be unique - one piece will only fit with one other piece.

Designing the Bare Bones Puzzle Piece

Next, start thinking about how to organize your classes. Many board game design questions follow a similar pattern: there are game pieces, the board, and the player or solver. So with that in mind, this problem can be broken into three classes: the puzzle pieces, the board, and the solver.

We could either design the smallest component first and work our way up, or we can design the big picture first and then fill in the details. I decided to start with the puzzle piece and build up because getting the puzzle piece abstraction right is central to being able to solve the puzzle.

To get us started, we know that each puzzle piece has 4 sides. This makes me think that Side should be a subclass of Piece, and Piece should hold 4 Side objects:

public class Piece {
  private Side side1, side2, side3, side4;

  public class Side {
  }
}

One decision to make here is whether the Sides should be put in a data structure or left as four individual variables. I opted to leave them as individual variables because we don't stand to gain much from putting them into a data structure; it won't make the code any faster or more readable.

The Side

Each side has two properties: 1) it can jut out, in, or be flat and 2) the curvature of the indentation/extrusion. We'll say the sides of two pieces fit together when one is IN, the other is OUT, and they both have the same curvature. Without getting too specific yet, we can start to fill in Side:

public class Side {
  private enum Edge {IN, OUT, FLAT}
  private Edge edge;
  private Curvature curve;   
}

You may be thinking, what is Curvature? In an interview setting, you need to set a boundary for how specific your design is going to get. Don't get bogged down trying to define every last component; getting the big picture down first is more important. For that reason, I would leave Curvature undefined on the whiteboard at this point, but I would tell my interviewer what I imagined it looked like - i.e. it contains some property that I can use to match up two pieces, like maybe the angle of the extrusion's arc.

The Board

We have a functional puzzle piece class now, so let's zoom out and start thinking about how we're going to hold all of them. We need a way to track two components of game state: the pieces that have been played and the unused ones.

Since we know that the board is a rectangle, we can represent the board as a 2D array. As for the unused pieces, we have several options for how to represent them - we could put them in a list, a queue, or a graph, to name a few. Let's say we'll be cycling through the pieces one-by-one to solve the puzzle. In this case, we can use a queue to quickly grab the next piece, or return it to the back if we couldn't find a match for it.

The board looks like this:

public class PuzzleBoard {
  private Piece[][] board; get;
  private Queue<Piece> unusedPieces; get;

  public void placePiece(Piece p, int row, int column) {
    board[row][column] = p;
  }

  public Piece getNextPiece() {
    return unusedPieces.pop();
  }

  public void returnPiece(Piece p) {
    unusedPieces.push(p);
  }
}

The Solver

The Solver class will need to take in an unsolved Board and return a solved Board:

public class Solver {
  public PuzzleBoard solve(PuzzleBoard puzzle) {
    //solve puzzle
  }
}

Let's think about how to solve this puzzle. We don't need to reinvent the wheel; we can use the standard heuristic of first finding the corner pieces, then the edges, and then filling in the middle pieces.

Before we get to that, we'll need to add a matcher method as well as some helper methods to the Piece and Side classes so we can easily identify edges and corners:

public class Piece {
  private Side side1, side2, side3, side4; get;

  public boolean matches(Piece other) {
    if ((side1.curve == other.side3.curve) 
        && ((side1.edge == Edge.IN && side3.edge == Edge.OUT)
        || (side1.edge == Edge.OUT && side3.edge == Edge.IN) ... ) //etc- check all opposite sides
  }

  public boolean isCornerPiece() {
    if ((side1.isEdge() && side2.isEdge()) || side2.isEdge() 
        && side3.isEdge() || ...) //etc - check all adjacent sides {
      return true;
    }
    return false;
  }

  public boolean isEdgePiece() {
    if (isCornerPiece()) {
      return false;
    }
   if (side1.isEdge() || side2.isEdge() || .. //etc - check all sides) {
        return true;
  }

  public class Side {
    private enum Edge {IN, OUT, FLAT}
    private Edge edge;
    private Curvature curve;

    public boolean isEdge() {
      return edge == Edge.FLAT;
    }
  }
}

Now we can finish off the Solver:

public class Solver {
  public PuzzleBoard solve(PuzzleBoard puzzle) {
    while (puzzle.getUnusedPieces().getNextPiece()) {
      //find corner pieces
      //find edge pieces
      //finish the puzzle
    }
  }
}

I'm choosing to leave the algorithm as vague instructions as a time-management technique. In my own interview, I was almost out of time at this point, and seeing as the focus of this interview is not to evaluate my algorithm design skills, it's not important to fully flesh out an algorithm.

Gotchas

This is the point in the interview where the interviewer starts asking questions to try and test how good your design is. My interviewer added the additional requirement that we needed to be able to rotate pieces.

To handle this, we'd need to make several changes. For one, we'd need to add a rotate() method to the Piece class:

public class Piece {
  private Side side1, side2, side3, side4;

  public void rotate() {
    Side extraSide = side1;
    side1 = side2;
    side2 = side3;
    side3 = side4;
    side4 = extraSide;
  }

  public boolean isCornerPiece() {
    if ((side1.isEdge() && side2.isEdge() || (side2.isEdge() && side3.isEdge() || ... ) //etc - check all adjacent sides) {
      return true;
    }
    return false;
  }

  public boolean isEdgePiece() {
    if (isCornerPiece()) {
      return false;
    }
   if (side1.isEdge() || side2.isEdge() || .. //etc - check all sides) {
        return true;
  }

  public class Side {
    private enum Edge {IN, OUT, FLAT}
    private Edge edge;
    private Curvature curve;

    public boolean isEdge() {
      return edge == Edge.FLAT;
    }
  }
}

In the Solver, we'd need to add logic to try rotating the piece if it doesn't fit initially. The ability to rotate pieces also introduces some uncertainty into the Solver - we are no longer sure that when we put a corner piece down, we're putting it into the right spot. So we would also need to add backtracking to our algorithm to account for this.

Wrapping it Up

Resources

Here are a few resources that helped me understand OOD principles:

Final Thoughts

Object-oriented design is a broad topic. You first need to master the foundations - like the concepts of abstraction, encapsulation, inheritance, and polymorphism - before moving on to more advanced topics like design patterns and SOLID principles. Most importantly, you need to practice in order to learn. So I'll leave you with a few questions for you to design your own solutions for:

  • Design a bookstore inventory management system.
  • Design a parking lot.
  • Design a Monopoly game.

And please let me know if you liked the video!

Discussion (3)

pic
Editor guide
Collapse
nicciwill profile image
MsNicciWill

Hi Sam,

I watched the video with Lusen, then came to your blog for the deets. I'm a mid-level dev and I found the breakdown of your thought process to be extremely insightful. Thanks so much for sharing!! P.S. - Here's a +1 vote for a future post on design patterns and SOLID principles, too :)

Collapse
candidateplanet profile image
lusen / they / them 🏳️‍🌈🥑

Sam I love the details in your explanation \o/ !!

Collapse
techdebtor profile image
sam Author

Thanks 😸My only regret is that I couldn't go into more depth on design patterns and SOLID principles without making the post too long! Maybe that will be another post 👀