Assignment #2: Tech Jobs OO

Assignment #2: Tech Jobs (Object-Oriented Edition)

Introduction

Your apprenticeship at LaunchCode is going well! Only a few weeks in and you’re regularly making contributions to code that will eventually be used by all LaunchCode staff.

Your last task was to get the prototype Tech Jobs app in good shape. Now it’s time to advance the underlying structure of the program.

Your mentor on this project is Sally, one of the developers at LaunchCode. She regularly supports coders who are just getting started with their careers.

Image of Sally

After seeing your strong work with your last project, Blake reported that you performed well and learned quickly. Because of your success, he and Sally feel comfortable assigning you to a set of tasks that are a notch up in difficulty.

Sally completed some initial work on the project and left you some TODOs.

Learning Objectives

In this project, you’ll show that you can:

  1. Read and understand code written by others.
  2. Work with objects to encapsulate data and methods.
  3. Use the generator in IntelliJ to automate routine tasks.
  4. Use unit testing and Test-Driven-Development (TDD) to verify and create new methods.
  5. Apply the concept of inheritance to streamline your classes (the DRY idea—Don’t Repeat Yourself).

Get the Starter Code

Note

You may need to enable actions within your github repository if you have not done so already. Please refer back to the instructions on how to do so in the Running the Autogtrading Tests through Github Actions section of Assignment 0

In Canvas, Graded Assignment #2: Object-Oriented Edition contains a GitHub starter code repo link. Fork the repository to your personal profile, copy the repo’s URL for cloning, and open up IntelliJ. and then set up the project in IntelliJ. Refer back to the setup instructions from assignment 0 for more details.

Introduction

Sally has gotten the ball rolling by adding a Job class, along with classes to represent the individual properties of a job: Employer, Location, PositionType, and CoreCompetency. She completed the Employer class, and she left you the task of filling in the others.

As the team gets closer to deploying the app—and abandoning the test data they’ve been using—they’ll want an easy way to add and remove jobs via a user interface(UI). Before that, however, you need to finish shifting the project to an object-oriented design.

Why Change to Object-Oriented?

Working with data stored as strings in HashMaps and ArrayLists isn’t a good long-term solution, for reasons that we point out below.

The Job class introduces an object-oriented design to the application. It contains all of the fields you used in the console version of TechJobs: name, employer, location, positionType, coreCompetency. There’s also an id field which will be used to uniquely identify Job objects.

The main difference between the object representation of a job and the string-based representation is that the values of employer, location, and the other non-ID fields are no longer strings. Instead, they are classes of their own.

Job Fields

Open the Job class file. You’ll see the following fields (among others):

10
11
12
13
14
private String name;
private Employer employer;
private Location location;
private PositionType positionType;
private CoreCompetency coreCompetency;

Of these, only name is a string. Sally created classes to represent each of the other properties. These classes—Employer, Location, CoreCompetency, PositionType—have value and id fields.

So, for example, if you had a Job instance, you could get the name of the employer this way:

// job is an instance of Job
String employerName = job.getEmployer().getValue();

Additionally, the toString() method of the Employer class is set up to return the value field. Thus, using one of these objects in another string context like System.out.println will print the data stored in value.

// Prints the name of the employer
System.out.println(job.getEmployer());

Why do we go to all of this trouble when we could store this job-related data as strings? There are a couple of reasons.

Eliminate Duplication of Data

In our app, we have multiple jobs that have the same value in a given field. For example, there are multiple jobs with position type “Web - Full Stack”, and each employer may list several jobs. If we store the values of these fields as strings directly within each Job object, that data would be repeated in several places across the application.

By using objects, we can have a single PositionType object with value “Web - Full Stack”. Each job that wants to use that position type holds onto a reference to the given object. Similarly, we can have one Employer object for each employer.

Aside from reducing the amount of raw data / memory that the application uses, this will allow data to be updated more easily and properly. If we need to change the name of an employer (e.g. due to a typo or a name change at the company), we can change it in one place—the single Employer object that represents that company.

Enable Extension

While the four Job properties represented by objects will primarily be used for their string values, it’s easy to imagine adding new properties to address future needs.

For example, it would be useful for an Employer object to have an address, a primary contact, and a list of jobs available at that employer.

For a Location object, useful information includes a list of zip codes associated with that location, in order to determine the city and state for an employer or job.

If we were to store these four new properties as strings within the Job class, extending and modifying this behavior would be much more complicated and difficult moving forward.

Your Assignment

Running the Autograding Tests

Before diving into your tasks, review Assignment #0: Hello, World! for details on running the autograding tests for this assignment. This assignment has many more tests than the previous two, so we’ve organized them into separate files.

File tree image

Each of the one test files, TestTaskXXXX, contains the tests to grade one of the six tasks outlined in below (there’s no coding work for your first task, so there is no TestTaskOne). Run all of the tests by right-clicking on the org.launchcode.techjobs.oo and selecting Run tests...

menu for running tests

You should see a large number of failures along with a small number of passing tests. Your job is to get those failures to pass, while not breaking the few tests that already pass.

output for failing tests

When you start on one of the tasks below, begin by running only the tests associated with that task. To do so, right-click on the test file and select Run TestTaskXXXX.

output for failing tests

As you work on the components of the given tasks, continually re-run the tests to see the failing tests gradually turn to passing. When all tests within the file pass, you’re ready to move onto the next task.

Your tasks

The list below provides a general overview of your assigned tasks. Specific details for each part appear in the following sections, so be sure to read them carefully as you solve each problem.

  1. Review Sally’s code in the Employer class to learn how to assign a unique ID.
  2. Add getters, setters, and custom methods as needed to the Location, CoreCompetency, and PositionType classes.
  3. Complete the Job class using what you learned in steps 1 and 2.
  4. Use unit testing to verify the constructors and equals methods for the Job class.
  5. Use TDD to design and code a custom toString method for the Job class.
  6. Use inheritance to DRY the code within Employer, Location, CoreCompetency, and PositionType.

Next