Category Archives: CS@Worcester

Breakable Toys

Breakable toys are small programs you can develop and alter freely, without repercussions if something goes wrong. Often expecting something to go wrong as we learn more from our mistakes and successes. This freedom allows you to experiment and push your limits, creating an opportunity to further develop your knowledge in whatever program or system you are working with.

Reading this pattern has made me realize that almost everything I know about programming has been learned through breakable toys. I have always treated school assignments as breakable toys, with a deadline for no longer being broken. Trying to add features to the project that would force me to learn something new. Through trial and error and not just learning what works and what doesn’t but understanding why they do or don’t. Sometimes, revisiting old projects well past their due date to add features. My go-to breakable toy when learning a new language syntax has always been a decimal-to-binary calculator that can eventually support other bases.

Understanding how big of an impact breakable toys have had on my programming skills, I realize the importance of revisiting them along with making new ones to grow my toolbox. The reading provided a lot of good examples of breakable toys that I can work on and develop in the future. As someone who uses a wiki daily, I have never thought about developing my own until now, and as the reading suggests it would provide a lot of opportunities to develop new features as I go. Other important breakable toys will continue to appear as I learn more

Moving forward I am going to make sure I always have a breakable toy that I am working on and developing. To have many breakable toys at my disposal when it comes to solving problems in projects that do not have the luxury of being breakable. Getting ideas and inspiration for new breakable toys is going to be based on what skills I need to focus on. With those required for my profession at the forefront of the list of breakable toys I need to work on.

From the blog CS@Worcester – CS Learning by kbourassa18 and used with permission of the author. All other rights reserved by the author.

Week 11 Blog

This week’s blog will cover the main purpose of Object Oriented Testing and its usefulness. You most likely have heard the term “Object Oriented Programming”, which refers to a style of programming that utilizes classes, abstract classes, inheritance, polymorphism, concurrency, and more as a way of organizing code. These tools can be useful when dealing with multiple lines of code because it can be broken down into multiple files creating a more organized and readable product. Having a file with thousands of lines of code is a developers nightmare. Object Oriented Testing aims to test these systems and ensure they are behaving as expected. It is possible to have too much inheritance in a program, making it difficult to find where a piece of code is located, slowing down development. Unlike other test methods that primarily test function behavior, Object Oriented Testing analyzes the behavior of the entire class and its interactions with other files.

There are multiple techniques to Object Oriented Testing: Unit Testing, Integration Testing, Inheritance Testing, Polymorphism Testing, and Encapsulation Testing just to name a few. Unit testing refers to testing of individual components of the class before testing the interactions it has with other classes. Initially testing the classes functions will prevent scenarios where you can’t locate the bug in the program because there are too many inherited classes. An example is testing each function and ensuring the behavior. Integration testing refers to testing objects of different classes and ensuring they behave properly with all the components. Inheritance testing aims to test the relationship between parent and child classes. This technique of testing also tests overridden functions are properly implemented and are actually overriding the function. Polymorphism testing aims to verify that objects of different types can be used interchangeably. This type of testing ensures the behavior across all types of objects. Encapsulation testing tests access control and ensures the data being accessed is allowed to be accessed by the user.

The main benefits of running these tests is to detect defects early on rather than later in the development process. For this reason, it’s recommended to run tests throughout development. Object Oriented Testing ensures our project is modular, making it easier to maintain. In addition, it becomes easier to implement new features and classes without impacting existing code. Due to the never-ending demands of modern applications and the ever-evolving tech industry, the scalability of a program is crucial.

Blogs chosen: https://medium.com/@hamzakhan522001/object-oriented-testing-1f9619da40d0
and https://www.h2kinfosys.com/blog/object-oriented-testing/

From the blog CS@Worcester – Computer Science Through a Junior by Winston Luu and used with permission of the author. All other rights reserved by the author.

Test-Driven Development: Because Debugging is Overrated.

You know that heartbeat you skip when you press ‘run’ and pray everything works? Well, today I shall exhibit a certain method that has been around for some time that will have you save those skipped heartbeats for when your favorite TV show character nearly dies. Enter Test-Driven Development (TDD) – it’s kind of like having a buddy checking your work as you go, making sure you’re on track

Imagine you start cooking a new recipe you found. Would you start cooking without checking if you’ve got all the ingredients? You write a small test for a feature you’re about to whip up, see it fail (because it doesn’t exist yet), and then write just enough code to pass the test. It’s a cycle: write a test, code a bit, make it pass, and clean up your code without changing how it works. Rinse and repeat.

Yes, I’m not a telepath but I know what you are thinking right now, why even bother?

One benefit of TDD is that it nearly eradicates most of the bugs in your code, making you less likely to spend hours hunting down bugs. You’re checking your steps as you go, so you know exactly where things might have gone sideways.
Your code design is going to be more professional because when you write your tests first you can make your code more modular and easier to read, kind of like organizing your closet so that you can find your favorite shirt even in the dark.
Once you have a couple of tests, guess what? You can go update or refactor your code however you like, your tests will let you know if you broke something.
Apparently, the word online is that after getting used to it you’re actually going to code faster. The backtracking time to fix bugs adds a lot to your programming timer even if it doesn’t feel like it.

Okay, It’s not all Sunshine and Rainbows. I personally feel like Test-Driven Development feels like a drag at most times, especially for people who are not used to writing tests before you code, and from what I have experienced so far, writing good tests is an art form on its own. Still, once you start, you might just want to stick with it. The payoff in reducing headaches (I promise I’ll stop using this word in the future) and quality code will be worth it.

I really want to think of TDD as my coding companion, helping to keep my code clean and bug-free. It is somewhat of a mindset shift, more frontloaded work for sure but I feel like it will result in fewer late-night coding sessions and better-quality projects. Whether you are a solo developer or a team player, giving TDD a shot could be a game-changer. So try leading the way with tests next time you sit down to code and see how that goes.

Till next time,

Ano out.

References

https://testdriven.io/test-driven-development

https://www.browserstack.com/guide/what-is-test-driven-development

From the blog CS@Worcester – Anairdo's WSU Computer Science Blog by anairdoduri and used with permission of the author. All other rights reserved by the author.

Enhancing Code Quality: A Dive into Smoke and Acceptance Testing, Exploratory Testing, and Static Analysis in JUnit

In the world of software development, ensuring code quality is paramount. It’s not just about writing code that works; it’s about ensuring that the code is robust, reliable, and maintainable. This is where various testing methodologies and tools come into play. In this blog post, we’ll explore three crucial aspects of code quality enhancement in JUnit: Smoke and Acceptance Testing, Exploratory Testing, and Static Analysis.

Smoke and Acceptance Testing: Smoke testing, also known as build verification testing, is a preliminary test that focuses on ensuring that the most critical functionalities of an application work. It aims to identify fundamental issues that might hinder further testing. Acceptance testing, on the other hand, evaluates whether the software meets the acceptance criteria and is ready for release.

JUnit, a popular testing framework for Java, offers robust support for both smoke and acceptance testing. Through annotations and assertion methods, developers can easily write tests that verify the functionality of their code. By running these tests regularly, developers can catch regressions early in the development cycle, thereby ensuring a smoother development process and a higher quality end product.

For further information on Smoke and Acceptance Testing, you can refer to the documentation here.

Exploratory Testing: Exploratory testing is a hands-on approach where testers explore the software application without predefined test cases. Instead, testers rely on their domain knowledge, intuition, and creativity to uncover bugs and issues. While automated tests are valuable, exploratory testing can uncover issues that automated tests might miss.

In JUnit, exploratory testing can be facilitated through the use of parameterized tests and dynamic test generation. These features allow testers to generate test cases dynamically based on various inputs, enabling thorough exploration of the codebase.

To learn more about Exploratory Testing, you can explore the documentation here.

Static Analysis: Static analysis involves analyzing the code without executing it, typically to find potential defects or code smells. In JUnit, static analysis can be performed using various plugins and integrations with static analysis tools like FindBugs, PMD, and Checkstyle. These tools analyze the codebase for issues such as potential bugs, code style violations, and performance bottlenecks, providing developers with valuable insights into improving code quality.

For detailed information on Static Analysis in JUnit, you can refer to the respective documentation of static analysis tools and plugins integrated with JUnit.

In conclusion, leveraging Smoke and Acceptance Testing, Exploratory Testing, and Static Analysis in JUnit can significantly enhance code quality, leading to more robust and reliable software applications. By incorporating these practices into the development workflow, teams can streamline the testing process and deliver higher quality code with confidence.

From the blog Discoveries in CS world by mgl1990 and used with permission of the author. All other rights reserved by the author.

CS448 Software Development Capstone: Apprenticeship Patterns – “Reading List”

After my week of spring break, I’m looking to get back to building constructive habits and reinforcing my software development fundamentals. I was inspired to return to this chapter of the “Apprenticeship Patterns” textbook because I recently learned about a computer science problem called the Circle-Ellipse problem.

This hypothetical problem is meant to highlight the limitations of the object-oriented programming paradigm, specifically when using subtype polymorphism in your class design. In the Circle-Ellipse problem, two classes are defined, Circle and Ellipse, with the Circle class inheriting from the Ellipse class. The Ellipse class includes two member methods, stretchX() and stretchY() which can modify, or mutate, two private member variables of Ellipse each representing an X and Y coordinate. The programming language understands all instances of the Circle class as also being instances of the Ellipse class with this inheritance relation. The problem arises when considering the requirements of a subclass. A subclass needs to implement all the member variables and methods of its parent. The Circle class needs to implement stretchX() and stretchY() as a subclass of Ellipse. Using either of these methods to change the dimensions of the Circle would consequently make that object no longer represent a mathematically correct circle.

As this problem was explained to me, the Liskov Substitution Principle was mentioned. I remember reading about this principle as one of the 5 SOLID software design patterns. The Liskov Substitution Principle essentially states that in a program using subtype polymorphism, an object ought to be able to be substituted by one of its subclasses without breaking the program. The Circle-Ellipse problem represents a violation of this principle because an Ellipse cannot be substituted for a Circle except in one very specific case.

I hadn’t considered the limitations of inheritance relationships in software design before learning about this problem. I decided that after the lecture where I learned about the Circle-Ellipse problem, and after seeing so many titles and authors name dropped in “Apprenticeship Patterns”, that I should start compiling a reading list and start more intentionally defining my daily schedule, including time for reading about software design and computer science. I started with a summary of the Circle-Ellipse problem, and then went through the appendix in “Apprenticeship Patterns” to choose a few books that the authors cited the most often.

The pattern introduces the possibilities of making your reading list public on the internet or using an existing list to source further reading material. The reader is also prompted to look ahead to the future and maintain the reading list to use for reflection on their learning journey.

From the blog CS@Worcester – Michael's Programming Blog by mikesprogrammingblog and used with permission of the author. All other rights reserved by the author.

Chapter 4 of “Apprenticeship Patterns: Guidance for the Aspiring Software Craftsman” focuses on the concept of “Confront Your Ignorance.”

This chapter highlights that acknowledging your limitations is key to growth. It offers a roadmap for identifying these gaps and strategies for filling them.

The chapter lays the foundation with the Dreyfus Model, a roadmap for skill development. It breaks down learning into five stages: Novice, Advanced Beginner, Competent, Proficient, and Expert. The authors emphasize understanding your current level and adopting a lifelong learning mentality.

Imagine your skills and experiences as a developer stacked together, like a toolbox. This toolbox is your “knowledge portfolio.” The chapter argues that for a successful, long-lasting career, you shouldn’t just have a hammer. Instead, aim to be a “generalizing specialist.” This means having a go-to tool (deep expertise) but also filling your toolbox with various other useful tools (proficiency in diverse areas). This versatility allows you to tackle more problems and adapt to changing needs in the software-development world.

The chapter outlines several strategies for effectively addressing your ignorance:

  1. Build a Solid Foundation: Focus on mastering the fundamentals of your field. A solid foundation will prepare you for more advanced learning and future growth.
  2. Learn How You Fail: Reflect on past experiences, both successes and failures, to identify areas where you can improve your knowledge. Use these insights to guide your future learning.
  3. Expose Your Ignorance: Accept that you’re still learning and don’t be afraid to admit you don’t have all the answers. See your knowledge gaps as steppingstones to becoming a master.
  4. Confront Your Ignorance: Don’t shy away from opportunities to learn. Ask questions, take classes, and constantly seek out new information to fill in the gaps in your understanding.
  5. Find Mentors: Seek out experienced individuals who can mentor you and share their knowledge. A good mentor can offer valuable advice and insights based on their own experiences.

The interesting and useful concerns about this chapter is it discusses the importance of recognizing and accepting that you don’t know everything. It encourages embracing your ignorance as a steppingstone to learning and growth.

This chapter has changed the way i think about my profession as it emphasizes the importance of continually learning and expanding your skills beyond just coding. It suggests that software development is not just about writing code but also about understanding the business domain, interacting with customers, and collaborating effectively with others.

In essence, Chapter 4 of “Apprenticeship Patterns” emphasizes the significance of admitting what you don’t know as a software developer. By recognizing your boundaries and actively pursuing chances to learn and improve, you can strengthen your abilities and progress in your software development career.

From the blog CS@Worcester – THE SOLID by isaacstephencs and used with permission of the author. All other rights reserved by the author.

CS-448 Week 8 Long Road

The pattern of “The Long Road” highlights a common dilemma faced by aspiring software developers in today’s fast-paced industry. It contrasts the culture of instant gratification and superficial success with the desire to pursue mastery and craftsmanship in software development.

What intrigues me about this pattern is the disconnect between the long-term goals of becoming a proficient software developer and the short-term pressures to prioritize immediate financial gain and career advancement. Especially early in their careers, developers find themselves torn between these conflicting expectations while navigating through the complexities of the industry and trying to establish themselves.

This pattern resonates with me personally because it highlights the internal struggle I have faced in my own journey as a software developer. While I have not had any significant offers in the field of work yet, I know that true fulfillment in this line of work comes from the pursuit of excellence, continuous learning, and honing one’s craft over time. With my focus on excellence in my personal craft, it will pay off for me in the future later down the road.

The notion that the lessons and wisdom of seasoned software developers often goes unheeded in an industry that is constantly chasing the next big thing I found thought-provoking. The lack of knowledge transfer between generations of developers leads to the repetition of past mistakes and the reinvention of the wheel.

This pattern has caused me to reconsider my approach to my intended profession and how I want to work. Rather than falling into the external pressures and expectations, I am more committed to stay true to my passion for software development and prioritizing personal growth and mastery over short-term gains.

While I understand the advice to prioritize financial stability and career advancement, I do not completely agree with the notion that slow and steady skill-building is somehow less valuable or important. I believe that the pursuit of mastery is what ultimately sets exceptional developers apart and leads to long-term success and fulfillment in this field. I remain steadfast in my commitment to honing my skills, embracing lifelong learning, and striving for excellence in my craft, regardless of the trends or societal expectations.

3. Walking the Long Road | Apprenticeship Patterns (oreilly.com)

From the blog CS@Worcester – Jason Lee Computer Science Blog by jlee3811 and used with permission of the author. All other rights reserved by the author.

Learning Never Stops

I decided to read the “Reading List” section from the “Construct your Curriculum” chapter, and I found it quite eye-opening. I have read some general books related to software development and computing, whether discussing theory or practical information. However, I must admit that most, if not all, of what I have read has either been out of necessity for course requirements or coursework-related. I have yet to build a list of literature to read or go out to seek literature to read now. After viewing this section, I will get started looking deeper into the literature related to the particular fields I’m interested in to aid me in my future profession(s).

While there is plenty to read and endless amounts of information to consume, it’s important to find things that are related and applicable to my work or studies. At this current moment, I am interested in software development in general, but I would like to get into the fields of robotics and/or artificial intelligence after graduation. Even though these topics are constantly changing and evolving, I can find some good literature to aid in building my overall knowledge related to such topics.

With the advent of the internet, text is no longer purely physical, and I can access even more literature than ever before. But with that perceived benefit also comes the caveat of there being too much for one person to reasonably consume. There are plenty of resources I can use, though, including the internet, peers, and/or mentors. Utilizing such resources can aid in my sifting through the unnecessary filler content to delve into text that will meaningfully add to my knowledge base. Even if something may not be useful directly at the moment, I also recognize that important information isn’t always apparent at the exact moment it’s consumed. Focusing on my present needs but also tending to potential future ones, will most definitely add to my progress on my craftsman journey.

I recognize that my learning must never come to a halt since complacency could easily lead my path toward becoming a master craftsman to become derailed either temporarily or permanently. By looking for and curating literature to serve my own needs and wants related to my present and future professions, I will be able to become a well-informed craftsman while remaining open-minded to new and ever-rapid changes within the entire computing field, whether that lies in practical work or research. Regardless of what field I venture into, this skill will always serve to benefit my work and hopefully help me aid others in their journeys as well.

From the blog CS@Worcester – Eli's Corner of the Internet by Eli and used with permission of the author. All other rights reserved by the author.

Test Driven Development

When you go to write code, maybe you already know what you want the code to do, knowing what it should give you as outputs and answers, but you might not know how to go about writing the code itself. In test driven development, you start with writing the tests first, and then trying to pass those tests, slowly as you go. It sounds like a strange approach to it but it is not as bad as it sounds.

In this blog post, Arek Torczuk talks about test driven development, and how it is the best thing that can happen to software development. First, they start off by describing test driven development, where they say it is, simply, a failing phase, a passing phase, and then a refactoring phase. In the failing phase, we create a test that will fail. In the passing phase, we create or write code, minimal code, that will pass the test. In the refactoring phase, we clean up the tests. Typically with coding, you would write the code, and then write tests. However, Torczuk presents some problems with this way of code development, like when to stop writing tests, or when you are sure implementation is finished. With test driven development, they say there are benefits, such as when writing tests, it makes you ask yourself, what do you want the code to do. They say that you should know the answers to these tests before the code is written. They then go on to provide situations where code may be impossible to test, and how test driven development can be used to help that, like using mocking. They provide code examples with these too, to further help visualize solutions. They provide some additional sources at the end of the article in the event you would like to learn more about test driven development. 

This is a strange way to write code, and for those used to writing code before everything else, this can be a difficult adjustment. Personally, I found it fairly difficult to start, but afterwards I was able to write the tests, and then write the code to pass those tests, and then keep doing that. The tests do provide a build up of the code, instead of doing everything all at once, which was what Torczuk was trying to get at with his blog post. It allows the tests to provide the framework of the code and lay it out. 

From the blog CS@Worcester – Cao's Thoughts by antcao and used with permission of the author. All other rights reserved by the author.

The Power of Consistent Practice

Summary

In the world of software development, the mantra of “Practice, Practice, Practice” resonates deeply with aspiring craftsmen. This pattern from the book Apprenticeship Patterns by Dave Hoover and Adewale Oshineye emphasizes the critical role of deliberate practice in mastering any skill, especially in the realm of programming.

My Reaction

The essence of this pattern is simple yet profound: improvement comes through consistent and focused practice. As I delved into this pattern, I couldn’t help but reflect on my own journey as a budding software developer. Often, I find myself oscillating between bouts of intense coding sessions and periods of procrastination. This pattern serves as a wake-up call, reminding me that true growth stems from disciplined and purposeful practice.

What struck me as particularly insightful about this pattern is its emphasis on deliberate practice. It’s not just about clocking in hours mindlessly; rather, it’s about setting specific goals, pushing oneself out of comfort zones, and seeking feedback to refine one’s skills. This approach resonates with the concept of “deep work” championed by Cal Newport, where undistracted focus on challenging tasks leads to substantial progress.

This pattern challenged my perception of talent and innate ability. The authors stress that talent is overrated and that mastery is achievable through dedicated practice. This perspective is empowering as it shifts the focus from fixed traits to actionable steps that anyone can take to improve.

However, I do have a slight disagreement with the notion that “talent doesn’t matter.” While I agree that hard work and practice are paramount, acknowledging individual differences in aptitude can also be valuable. Some may grasp concepts more quickly or possess a natural affinity for certain aspects of programming. Nonetheless, the core message of this pattern remains invaluable: consistent practice is the cornerstone of excellence.

As I reflect on how this pattern has influenced my approach to software development, I am inspired to adopt a more structured practice regimen. Setting aside dedicated time each day for deliberate practice, tackling challenging problems, seeking constructive feedback, and tracking progress are strategies I plan to implement rigorously.

The “Practice, Practice, Practice” pattern serves as a powerful reminder of the transformative impact of focused practice. It has reshaped my mindset, emphasizing the journey of improvement over notions of inherent talent. Through disciplined practice, I aim to embark on a path of continuous growth and mastery in software craftsmanship.

From the blog CS@Worcester – Hieu Tran Blog by Trung Hiếu and used with permission of the author. All other rights reserved by the author.