Build Your Own Feature

Designing, implementing, and testing your own ideas.

  1. Identify a feature
  2. Describe an interface
  3. Generate specifications
  4. Implement specifications
  5. Test implementations
  6. Reflect

It’s time to build your own feature for Husky Maps. In this project, we will identify a problem, describe an interface for addressing the problem, generate specifications for the interface, and implement and test prototypes based on your specifications. Unlike prior projects where you were given the problem, interface, and specification, we will now consider the broader design space of features we could have implemented and reflect on how our features inform our process to arrive at an efficient implementation.

Ultimately, you will submit a design document that showcases your thinking and contributions during each step. As you work on this project, it is critical to take careful notes and reflect on design process. There will be certain parts where students will be directed to generate descriptions or code: in addition to our general academic honesty policy that requires citing all prompts, be sure to identify how you add value to each step in the process.

While this project will engage the real-world considerations around designing features, for the purpose of this project, it is not necessary to actually integrate your feature into the Husky Maps app! It is only necessary to prepare a runnable Java prototype that demonstrates the possibility of the feature and your approaches. Think of this project (and all our prior projects) as about creating proof-of-concept programs that can help your team assess the potential performance trade-offs prior to dedicating your team’s full engineering effort toward a feature.

Identify a feature

Knowing what to build is just as important as knowing how to build it. Our first step will be to identify a feature by drawing on ideas submitted by the class.

Starting from the list of ideas posted in Ed Discussion, identify a feature you’d like to add to Husky Maps. Name the idea from the class list that inspired your feature. Explain why you chose the feature and how it would improve the Husky Maps app. If your feature needs an outside dataset, where can we find it or how can we generate it?

Your feature should be clearly representable as a data structures and algorithms problem that involves storing, retrieving, and searching for data in a structured and deterministic way. Avoid non-deterministic features inspired by machine learning algorithms, which will be difficult to test using standard JUnit assertions. While your feature should clearly engage with the data structures and algorithms concepts that are at the heart of this course, it is also important to justify your design process for selecting the feature. Consider the following brief example, which you may not use as your feature.

Nearest-neighbor search
Given a large number of (x, y) coordinate points (keys) with associated values, find the closest point to a particular (x, y) coordinate pair. This feature was inspired by the idea of proximity-based search that aims to prioritize results near the user or map center.

The Husky Maps dataset on Seattle is extracted from the OpenStreetMap project, which includes information about places such as coordinate locations, names, and inferred importance values. You may refer to an outside dataset beyond what’s already present in Husky Maps and note how you will obtain the data as shown above, but this will typically require more investigation and effort to integrate than features that do not require outside data. If you choose to use outside data, you may generate the outside data synthetically using randomness, inference from place name, or any other algorithm of your choice if it would be substantially easier than obtaining real data.

Describe an interface

After identifying a feature, we can work toward realizing it in code.

Describe an interface for your feature with at least 3 public methods that modify object state in a meaningful way. Discuss your design thinking behind each method by explaining how an alternative method or the removal of the method would impact usability. Provide specific details about intended behavior but avoid discussing implementation details.

Here’s a brief example for nearest-neighbor search, which shows how we might define an interface with three methods:

  1. Add one or more points; an alternative could be to provide all coordinate points directly to the search method, but this could be restrict the possibility to optimize future searches.
  2. Remove one or more points; without a method to remove points, users may not remove (or otherwise modify) existing information about places previously added to the object.
  3. Search for the nearest k points in the data structure; an alternative could be to search for the 1 nearest point in the data structure, but this is just k = 1.

Generate specifications

Use Microsoft Copilot with UW commercial data protection to draft 3 specifications that implement the interface.

  1. Visit copilot.cloud.microsoft and select “Sign in” at the top right.
  2. Log in with your UW email address and UW NetID password.
  3. Confirm that you are signed-into Copilot with your UW email address.

Each specification should implement the interface such that they produce the same expected outputs given the same inputs. Since generative AI is known to make mistakes, it is your responsibility to carefully review, select, and verify specifications for correctness.

Describe 3 specifications for your interface, where 1 specification is simple enough to manually verify by inspection while the other 2 specifications showcase your ability to apply and compose data structures and algorithms to produce efficient implementations. Explain how your 3 specifications draw on course concepts spanning at least 2 different course modules. Include a complete list of every prompt and chat message that contributed to your final submission, and how you added value to the process.

For nearest-neighbor search, a simple implementation could be based on storing elements anywhere in an array and sequentially searching for the nearest k points:

  1. Add points to the end of the array, resizing the array as necessary.
  2. Remove points by iterating over the array and shifting over subsequent elements after each removal, resizing the array as necessary.
  3. Search for the k nearest points by adding all points to a new PriorityQueue ordered by distance to the target before removing and returning k points.

On its own, this simple implementation draws on course concepts from the Deques module and the Priority Queues module.

Implement specifications

Implement 2 of your specifications, where 1 implementation is simple enough to manually verify by inspection. Add your interface and implementation classes to a new package within the project src directory following our approach to defining interface types and implementation types.

You may use Microsoft Copilot with UW commercial data protection to aid in implementation, but note that submitted code should primarily use only Java programming features and concepts that we have practiced either in this course or that you have learned in the prerequisite CSE 12X courses offered at UW. Out-of-scope Java features may be used sparingly with justification and clear explanation as to why it would be much more difficult to implement using only in-scope Java features.

Include a complete list of every prompt and chat message that contributed to your final submission. If you use out-of-scope Java features, explain why it would be much more tedious to reimplement the desired functionality without the out-of-scope Java features with a direct comparison against how it could be implemented using only in-scope Java features.

Test implementations

Test your 2 implementations against each other. Add your test files to the project test directory following our approach to defining abstract test classes and concrete test classes. Test cases may be written using any amount of randomness, including no randomness at all.

To assess test quality, your suite of test cases must achieve 100% coverage. Code coverage is a metric for determining which lines of program logic are actually evaluated in the process of running a suite of test cases. To check code coverage, right-click your testing file and choose Run Test with Coverage. Then, under the Testing Explorer, open the test coverage panel to view the current progress.

Demonstrate how your test coverage panel shows 100% coverage across statements, functions, and branches for your feature. Discuss one test case that addressed a specific code coverage gap that you identified through the testing process.

Reflect

Now that we’ve implemented and tested the feature, let’s reflect on our work so far.

What were you most proud of achieving through this project? Overall, how would you assess your use of generative AI? How did your expertise with data structures and algorithms contribute to the design, implementation, and testing process beyond what generative AI was able to suggest on its own?