Table of Contents
- Course Description
- Introduction
- Homework
- Exams
- Overall Thoughts and Conclusion
- Resources
Course Description
The course description from the CSE 143 Course Website:
Continuation of CSE 142. Concepts of data abstraction and encapsulation including stacks, queues, linked lists, binary trees, recursion, instruction to complexity and use of predefined collection classes.
Introduction
In Winter 2019, CSE 143: Computer Programming II at the University of Washington was taught by Hunter Schafer. I enjoyed the course a lot because it was different than what was taught in CSE 142. In 142, the class was centered around teaching the syntax and basic concepts. However, in 143, the course was centered around different data types. From these new concepts, the assignments (although were much more challenging) were interesting and held more significance. Even though CSE 142 is still a very important step to grasping the fundamentals, CSE 143 was more fulfilling and satisfying.
This post will outline my experience for the Winter 2019 CSE 143 course. It will be structured and organized very similar to my CSE 142 post. CSE 143 is also structured and organized very similarly to CSE 142, so reading my reflection on CSE 142 might also be useful. Along with outlining my experience, this post will also be a way for me to reflect on the course and its material. I will be revealing my thoughts and hope that this post will be useful to other students as well.
The code I have written for this class will not be publicly available in order to stop students from plagiarizing and instead I will offer the important aspects that I learned from each assignment. Prior to posting this publicly, on March 27, 2019, I emailed my instructor to read over this article in order to check for anything that might be deemed as academic misconduct. On the same day, my instructor emailed back giving me approval to post this.
Homework
For my quarter, there were a total of eight homework assignments. Each assignment similar to CSE 142, had their own specifications and sample outputs to check their external correctness. Many times, the outputs were a good broad check for external correctness. However, it is still always important to check edge cases to see if these special cases would affect how your program ran. Most of the points that I got deducted were from internal correctness. In all these assignments, it was important to remember about data abstraction and encapsulation.
- Abstraction
- removing "unnecessary" details to focus on and prioritize the essential aspects
- Encapsulation
- hiding implementation details away from the client/user
Being able to abstract and encapsulate your code is important in programming because it allows you to work at a higher level so that you can focus on parts that require more attention. As an example, we'll abstract a car so that it means it has tires and an engine to run. Instead of focusing on making the different parts of a car, we instead go around buying the parts individually in order to create a complete vehicle for a consumer. This is similar to what data abstraction and encapsulation is about. Instead of making each part individually, we just know that it needs tires and an engine. Additionally, instead of showing the consumer how we made the vehicle, we only teach them how to drive it since they don't really care about how the piston works inside an engine or how the tire moves individually.
Useful Tools for Homework
Output Comparison Tool
An important part to scoring well externally on the homework assignments is ensuring that your program actually creates the correct output. So, it was incredibly useful to use the Output Comparison Tool for this. However, it does not necessarily mean you shouldn't check other edge cases. In programming, not all test cases are given to you, so writing your own tests and running through them is still very important.
Eclipse
A few assignments into the course, I decided to switch to Eclipse from jGRASP. For CSE 142, I definitely still recommend jGRASP because of how it doesn't have all the extra features. By removing these features it allows you to focus on learning how to program instead of having it be autocompleted for you. However, after getting down the basics, I do recommend looking into using Eclipse because of that same reason. With all these extra cool features, I was able to focus on writing my code instead of getting distracted with the small details I missed.
Good Style and Clean Code
For a good score in homework for CSE 143, it is important to check for stylistic errors. I also think that it is necessary for them to grade our programming on style. Writing code with good style is fundamental, not only in collaborative work, but also for yourself. Being able to know what you wrote and why you wrote it is important so that the code can be understood in the future. For CSE 142, I said in my reflection that the mantra for that class was to reduce redundancy. However, for CSE 143, while reducing redundancy is still important, I think the mantra for this course was "don't reveal your implementation details." Throughout each assignment, we were not writing the main client program, but instead we were creating classes that would serve as helpers for the given programs. In this way, we had to encapsulate our programs so that it did not give away too many unnecessary implementation details that the client didn't need to know.
Javadoc
At the same time as I swapped from jGRASP to Eclipse, I also started to use Javadoc to write my comments. I definitely like using Javadoc because it gives me a standardized format to write my comments in. I also think it's really cool that by writing Javadoc comments, I can generate documentation using the comments I write in my programs.
Assignments
Homework 1: Letter Inventory
For this assignment, we were to implement a class to keep track of an inventory of letters. This homework assignment was an introduction to how we could work with classes in order to abstract arrays into an inventory that keeps track of letters. Another important factor for this assignment was that the values of characters have corresponding integer values and that allows for interesting usage with characters.
Homework 2: Guitar Hero
This assignment was really interesting because it had cool concepts that were unrelated to programming. Instead of focusing on the intricacies of these concepts, we were able to use different data types to emulate different details of a guitar. For example, we were able to generalize the plucking of the strings, the vibrations after plucking, and other properties that guitars have. By abstracting away the unnecessary details, we were able to create a cool program that emulated how guitars work using concepts like the Karplus-Strong algorithm.
Homework 3: Assassin Manager
In this assignment, we were introduced to a new data structure: linked lists. Using how linked lists are structured, it was perfect for emulating how a game of Assassin works where each person has a link to their target. It was important for this assignment to remember how linked lists worked and how they held references to other nodes. Also, it was incredibly helpful to draw pictures to visualize these references and how they would be affected if I was to rearrange the references.
Homework 4: Evil Hangman
Homework 4 focused on the Java collections classes and interfaces. The assignment had us write a class that kept track of the state of a "cheated" game of hangman in that it delayed choosing the word until it was necessary. The important part of this assignment was working with and modifying the different collections. By incorporating these different types of data structures, like sets and maps, it allowed us to have different ways to think of how we could store information and how they could interact with each other.
Homework 5: Grammar Solver
This assignment introduced us to recursion. Recursion is really interesting in that in a small amount of code, it can do a lot and create a lot of output. While recursion was the main focus, this assignment also gave us more practice with Java collections. This assignment showed us how we could work with grammar in the Backus-Naur Form. With how grammar is structured, it allowed us to use recursion to generate different strings based on the symbols in the grammar. Through how a symbol could lead to another symbol, it could theoretically lead to an infinite number of levels of symbols. With recursion, we were able to look at the symbols and if it included another symbol, we could go deeper and look at how that symbol was generated, and so on.
Homework 6: Anagram Solver
For Homework 6, it focused on recursion and more specifically, recursive backtracking. It was important to guard and restrict my recursive case so that my program would not do any unnecessary computation. As taught in class, I needed to "choose, explore, and unchoose." With recursive backtracking, it allows for us to look at all the possibilities and backtrack when necessary. Additionally, it was really cool that this assignment used the LetterInventory that we created in the very first homework assignment and showed me how we could use other classes and build on top of what we previously implemented.
Homework 7: 20 Questions
This assignment introduced us to binary trees and how we could use recursion to work with them. The important concept to remember for this assignment was the x = change(x) pattern where recursive methods would have to be designed like this to manipulate the structure of the binary tree. Instead of morphing and changing the data within the nodes, it was important to see how we could rearrange the nodes so that the links in the tree were adjusted correctly.
Homework 8: Huffman Coding
The last assignment was definitely really interesting because of how it implemented binary trees in such a unique way. We created a class that represented a Huffman Code made out of Huffman Nodes. It was really cool to see how a binary tree could be used in way that could represent a code of zeros and ones from the path between the node and the root of the tree. This was because of how binary trees have a left and a right subtree and through whichever path it took, each node would have its own unique code created from the path.
Exams
Once again, being similar to CSE 142, the tests for this course were handwritten. There were plenty of resources available for help. The exams were mostly not graded on internal correctness and primarily on external correctness. Both exams had "cheat sheets" attached to the back of them.
Practice-It
Similar to how I studied for the CSE 142 tests, I continued to use Practice-It to prepare for the exams. It was somewhat difficult to follow what the course covered in class to the problems on Practice-It because of how the course material started to jump between chapters in the textbook. However, it was not a very big deal and just took an extra minute to figure out what problems to do. I highly recommend it as a way to practice programming and prepare for the exams.
Here is the link for Practice-It.
Overall Thoughts and Conclusion
Coming from CSE 142, CSE 143 was definitely much harder, but also much more fulfilling because of how interesting and significant the assignments were. Combining what we learned from CSE 142 with the new course material in CSE 143, we were able to create programs that did impressive things. The main thing that I learned was the importance of data abstraction and encapsulation and how powerful it can be when done correctly.