CST338 • Week 7
← Back to all postsSolidly Tore Through the Semester
August 9, 2026
Opening Solitaire again now is honestly kind of fun because my first thought is that if I were doing this project today, I would absolutely turn it into a JavaFX game instead of keeping it text based. I definitely didn't come into this class knowing nothing about Java or software design. If anything, I came into the semester a little cocky because I already had experience with both and thought the class was probably going to be a piece of cake. Looking back at Solitaire, I can recognize a lot of concepts I already understood, but I can also see places where I would approach the design differently now after actually spending the semester working in Java. A really specific example is Game.getBoardDisplay(). My Game class manages the actual state of Solitaire, including the stock, waste, foundations, tableaus, move count, and win condition. Then getBoardDisplay() also builds the entire terminal UI, including all of the borders, headers, spacing, pile displays, and command text. If I rebuilt Solitaire today as a JavaFX application, I would keep Game focused on the actual state and rules of Solitaire and move the visual side into FXML files and controllers. Instead of Game creating a giant String representation of the board, the JavaFX controller could ask Game for the current state and update the cards and piles on screen after the player interacts with them. The concepts behind that change are separation of concerns and the Single Responsibility Principle. The game logic should not need to know whether I'm displaying Solitaire in a terminal, through JavaFX, or through something completely different. I think Project 2 has made that distinction much more obvious to me because now I'm constantly working between FXML views, controllers, models, DAOs, and database logic. It is also kind of funny because in my Week 4 reflection I wrote that for the next project I wanted to read through all of the requirements first and identify the relationships between the classes before I started writing code. I knew what I meant then, but I think I have a much stronger idea now of what those relationships and boundaries actually look like in a larger application.
One thing I'm genuinely really happy with is the Pile interface. Foundation, Tableau, Stock, and Waste are all piles of cards, so they share things like addCard(), removeTopCard(), peekTopCard(), isEmpty(), getCardCount(), and canAcceptCard(). At the same time, they have completely different rules for what cards they will actually accept. I like that I didn't try to force them all into behaving exactly the same way just because they were related. The interface gives them a shared contract, but Foundation can still worry about matching suits and ascending ranks while Tableau can worry about alternating colors and descending ranks. Looking back at it now, that abstraction actually held up really well as the project got larger. I also have to give my tests a little credit here. One example is testDrawCommand(). It checks that the stock goes from 24 cards to 23, the waste goes from 0 cards to 1, and the move count goes from 0 to 1. I like that it is actually checking the state change caused by the command instead of basically saying, “Well, the method ran without exploding, so I guess we're good.”
One area where I've grown is in how intentionally I apply OOP concepts. Interfaces, inheritance, encapsulation, and composition weren't brand new concepts for me coming into the course. The difference now is that I can think more about why I'm choosing one of them instead of another. Something like Pile is a good example. Foundation and Tableau share a common contract, but they don't need to share all of the same implementation. I'm thinking a lot more about the relationship between objects instead of just whether I can technically make one class extend or implement another. I have also gotten way better at thinking about separation between layers. Project 2 has forced me to think about this constantly. For my Accounts slice alone, I have FXML files, controllers, reusable components, a Player model, a DAO, SQLite, validation, and scene navigation. At this point I catch myself asking, “Okay, but which class should actually know this?” way more often instead of just putting code wherever I can access the information I need. Another thing that was actually new for me in this class was writing JavaDoc consistently. I have documented code before, obviously, but JavaDoc headers and documenting classes and methods in this specific way was not something I was used to doing. I'm honestly still adjusting to remembering them, especially when I get focused on making something work and want to immediately move on to the next thing. I understand the importance of them much more now, though. Once a project gets larger, especially when other people have to read and use your classes, having documentation that explains what a method expects, what it returns, and what the class is responsible for is genuinely useful and not just an assignment requirement. The other area where I think I have improved a ton is testing and debugging. Earlier in the semester I was already familiar with testing, but this class has given me a lot more practice testing Java specifically and thinking about what behavior I actually need to prove. For Project 2, I have written DAO tests for creating, finding, updating, and deleting players, tested things like duplicate usernames, and tested that data actually persists when I reconnect to the database. I have also spent a lot more time reading my teammates’ code through pull requests and debugging things that I did not personally write. That is definitely a different challenge than debugging something when I already know exactly what I was thinking when I wrote it.
The thing I think I'm leaning on the most in Project 2 is breaking one giant problem into a bunch of smaller pieces with really clear responsibilities. I actually wrote back during Solitaire that I work best when I can break requirements into small, testable steps, and Project 2 has pretty much confirmed that for me. This week has been Sprint 2, and I have basically been grinding through the remaining requirements for my Accounts slice. I'm actually having a lot of fun with it! There is something really satisfying about watching all of the separate pieces finally start connecting into an actual application instead of just being individual classes. My biggest challenge this week was definitely TestFX. This was my first time ever using it, although I have some experience with Selenium and Jest/Puppeteer from wayyy back, so I knew the gist of what it was supposed to do and loosely how it worked. I wanted the tests to actually open the JavaFX application, interact with the UI, click buttons, and verify what the user would see. Except every single time I had TestFX click a button, the entire program would shut down with an error. Because TestFX was new to me, my first assumption was that I had written my tests wrong. I spent HOURS debugging them, changing things, running them again, and trying to figure out what I had misunderstood. Eventually I started digging through the TestFX GitHub repository and found an issue involving macOS and the accessibility permission TestFX needs in order to interact with the UI. Like Bruh.. But after fixing the accessibility setting, my tests passed! It was super frustrating in the moment, but I actually think that experience is a pretty good example of how my debugging has developed. I knew what the test was supposed to be doing from my previous experience with browser automation, so after I kept narrowing things down and the behavior still did not make sense, I eventually stopped assuming my code had to be the problem and started investigating the tool and environment itself. Finding an existing issue in the actual TestFX repository was a much better answer than continuing to rewrite a test that was already doing what I wanted it to do. The part I'm watching most closely as we finish Project 2 is integration. This is the first project this semester where I can have code that works perfectly on my own branch and still run into a problem because four other people are working on different parts of the same application at the same time. I have to think much more carefully about how my controllers, models, database code, and scene navigation connect to everybody else’s work. Looking back at Week 1 compared with now, I would not say the difference is that I suddenly learned how software design works. I came into the course with experience and probably a little too much confidence because of it. I think the bigger change is that I'm much more deliberate now about how I apply the concepts I already knew, and I have added a bunch of Java-specific tools and practices on top of them. So apparently the class wasn't quite the piece of cake I thought it was going to be, but I'm really happy with how much more comfortable I'm building something this large in Java now.
Comments
Join the conversation for this post.
No comments yet. Be the first to comment.