Category Archives: CS-343

Data Redundancy – Relevance in Software Systems and Websites

In today’s world, businesses, organizations, and other entities that software and web developers consider “clients” heavily rely on being able to efficiently collect, access, and otherwise manage data for their day-to-day operations. For many, losing access to databases or similar outages hinders their ability to continue operations. In Data Redundancy: Meaning and Importance, author Charlotte White discusses data redundancy and some basic strategies and implementations to address these vulnerabilities.

Data Redundancy goes beyond simply having backups of existing data (although they’re an important component), it’s a proactive plan to prevent data loss and maintain smooth operations in the case of a server shutdown, hardware malfunction, or other major disruptive issue. It’s crucial for ensuring the continuity of business operations as website downtime often leads to financial losses especially for new websites or those with low traffic. Outages can also impact search engine rankings, as uptime is a factor commonly considered by search algorithms. Furthermore, failure to do so resulting in data loss can result in crashes/issues in other systems, loss of customer information, business details, and other critical and/or confidential information which is essential for an organization’s success and reputation.

How Redundancy Works: Effective redundancy designs reduce dependency on any single copy of data or data center. They commonly implement a 3-2-1 rule of backups, which means having three copies of data in two different locations, one of which is offline storage. Redundancy strategies should also consider factors like hardware redundancy; many servers use hard disk drives (HDDs) to store data which can fail due to simple wear and tear. Some hosting companies use RAID (Redundant Array of Independent Disks) and un-RAID solutions to mirror data from HDDs to other storage devices, minimizing the impact of HDD failures.

Recently in CS343, we’ve been looking at software architectures and strategies for organizing systems that could be realistically implemented to address clients’ needs. In particular, we’ve been considering the differences and strengths/weaknesses between a simpler architecture such as the Monolith versus a more complex architecture such as the MicroServices model, with several intercommunicating systems.

Most of the scenarios we discussed involved the ease of pushing out updates, but I was left wondering about the repercussions and ways to manage the possibility and reality of a database or system going totally offline. For businesses involved in eCommerce, uptime is money in terms of sales as well as maintaining search engine optimization. Given how damaging a disruption like this could be, data redundancy plans are an important consideration when planning and setting up a website or system. Understanding the value of D.R. and how they are implemented is an asset in planning and designing software systems and projects, and generally beneficial for computer science students and professionals.

Source:
1. Data Redundancy Meaning and Importance: A Complete Guide | ResellerClub India Blog

From the blog CS@Worcester – Tech. Worth Talking About by jelbirt and used with permission of the author. All other rights reserved by the author.

Week of October 9, 2023

https://www.atlassian.com/microservices/microservices-architecture/microservices-vs-monolith

Since learning about different software architecture styles like the monolithic architecture, the client-server architecture and the microservices architecture, I’ve been curious how large-scale applications transition from one architecture to another as the project grows in scale. I found this blog post on the Atlassian website breaking down the differences between the monolithic architecture and the microservices architecture, as well as telling the story of Netflix’s innovative migration from a monolithic architecture to a microservices architecture.

The article begins with the example of Netflix’s transition between architectures. Netflix was growing rapidly by 2009 and needed to expand its software infrastructure to meet the massive demand. Before “microservices” as a term was in wide usage, Netflix was one of the first major companies to migrate to a microservices architecture, and in 2015 earned a JAX Special Jury award for its successful deployment. Netflix’s new architecture would model itself on DevOps, defined by Amazon as “the combination of cultural philosophies, practices, and tools that increases an organization’s ability to deliver applications and services at high velocity (https://aws.amazon.com/devops/what-is-devops/#:~:text=DevOps%20is%20the%20combination%20of,development%20and%20infrastructure%20management%20processes.)”.

Following the story of Netflix’s change in infrastructure model, the article continues with an explanation of the monolithic architecture style. The monolithic architecture is a traditional design, which is defined by the application being housed in a single self-contained server. This architecture is simple to understand and easy to use as a foundation for your application. The major drawback of the monolith, however, is the difficulty in updating the application. Making changes to the code base requires bringing the entire service offline. Monolith architectures are not scalable with the growth of the application either.

The microservices architecture addresses some of the disadvantages that come along with a monolith architecture. The application is divided into independent services each with their own databases and methods. With this architecture model, only the components of the application that require changes need to be taken down, leaving the other components of the application free to continue working.

One inherent barrier to using the microservices architecture is the expense of multiple machines to host the different microservices, as well as storage space for their accompanying databases. It may only be beneficial for an application to transition to a microservices model once it has reached a certain scale. Small to mid-size applications may be perfectly well served by monolith architectures for much less cost than hosting the application across a microservices architecture.

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.

Exploring the Strategy Design Pattern in Software Development

I recently came across a fascinating article that I believe directly relates to our course material as it is the focus of our current Design Patterns Homework. In this blog post, I will provide a summary, share my reasons for selecting this resource, offer my personal insights, and discuss how this newfound knowledge can be applied to our future practice as software developers.

The resource I found is an article titled “A Beginner’s Guide to the Strategy Design Pattern,” available on the FreeCodeCamp website. This article serves as an introductory guide to the Strategy Design Pattern in software development. It outlines the pattern’s purpose, components, benefits, use cases, and best practices for implementation. The core idea of this pattern is to encapsulate a family of algorithms, making them interchangeable at runtime.

Why I Chose This Resource

I selected this resource because I was struggling with understanding the homework assignment and this article helped me better understand the strategy design pattern. Moreover, the article provides practical examples and clear explanations that make it accessible to beginners like myself.

Reflections on the Content

The article begins by explaining the core concept of the Strategy Design Pattern. It emphasizes the benefits of encapsulating algorithms into interchangeable strategies, including improved code flexibility, re-usability, and simplified testing. I found this concept to be highly relevant to our studies, as it promotes clean and maintainable code, a fundamental skill for any software developer.

The article discusses real-world use cases for the Strategy Design Pattern, such as sorting algorithms, validation rules, and payment processing. These examples helped me see the pattern’s practical application in various scenarios, and I can envision using it in my future projects.

Additionally, the article provides a step-by-step guide on how to implement the Strategy Design Pattern in Java, breaking down the process into clear, manageable steps. This hands-on approach was incredibly valuable as it demonstrated how to apply the theoretical knowledge in a real coding scenario much like the one seen in the Duck Simulator.

Application to Future Practice

Understanding the Strategy Design Pattern will undoubtedly benefit us in our future practice as software developers. Here’s how:

  1. Code Flexibility: By using this pattern, we can make our code more adaptable to changing requirements. It allows us to swap out different strategies at runtime, making our software systems more versatile.
  2. Re-usability: The Strategy Design Pattern promotes the re-usability of code. We can create a library of interchangeable strategies that can be applied to various projects, saving time and effort.
  3. Clean Code: Implementing this pattern encourages clean coding practices by separating concerns and reducing code complexity. This results in code that is easier to read, maintain, and debug.
  4. Testing: With strategies separated from the main object, testing becomes more straightforward. We can test each strategy in isolation, ensuring that it functions correctly.

Conclusion

In conclusion, the Strategy Design Pattern is a valuable tool in software development, and I believe this article provides a solid foundation for understanding and implementing it. As future software developers, mastering design patterns like this one will be essential for creating efficient, maintainable, and flexible code. I encourage you to read the article and explore this pattern further to enhance your skills in software development.

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

learning concurrency

I’ve heard these terms a lot, concurrency and multithreading, but I never really bothered looking into what they actually do. All I’ve really known about these terms was that they make things run faster. I mostly associated multithreading with hyperthreading, I’ve known that CPUs can use multiple cores for the same application to speed up runtime and make games perform better, but I was always sort of confused about how some games have issues with actually taking advantage of modern high-end CPUs. Usually, this is fixed by some sort of modification, if it’s been written already. That being said, my association between the two is only really surface level.

Hyperthreading is really just related to the physical hardware, which makes it different from multithreading in programming. Instead, multithreading is a form of concurrency in which a program has multiple threads that can run simultaneously, with each thread having its own operations and processes that it executes. What this ultimately means is that within a program, multiple operations can be executed at the same time.

This really fascinates me coming from the perspective of only writing straightforward code. While I sort of knew intuitively that programs can probably do multiple tasks at the same time, I’ve only experienced this on the end-user side of things, rather than the individual writing the program. After looking into how threads work in Java on a BairesDev post regarding Java concurrency, I can really see how powerful of a tool concurrency can be for runtime efficiency. This post essentially goes over what concurrency is and the ‘basics’ of utilizing built-in multithreading functions in Java, along with the advantages and disadvantages that this design comes with.

Of course, it does seem like it takes a careful approach to make sure that the implementation of such a tool is actually beneficial to the project. Even with this relatively simple tutorial, I did find myself a little confused at some points, particularly at the point where Locks are introduced. Though this could be the effect of the hour at which I decided to start writing this blog post, it still stands to reason that the complexity of writing a multithreaded program may result in a more difficult development process, especially in debugging.

Regardless, I was truly fascinated by the subject matter and I’m really excited to be going over concurrency in our course (CS-343). This seems like a tool I would really like to use as I enjoy toying with logistics in video games and the like.

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

Minimizing Anti-Patterns

The article I chose for this week’s blog post is “What Is an Anti-Pattern?” by Andreas Schöngruber. I chose this article because it discusses what anti-patterns are, gives some examples of anti-patterns, and how to avoid them. I chose this article for this week’s blog because it fits well with the syllabus topic of anti-patterns. I found the section about recognizing and avoiding anti-patterns to be very helpful. This blog post will focus on the aforementioned section about recognizing and avoiding anti-patterns in your code.

I will first discuss the section of the article which discusses recognizing anti-patterns in your code. One method that the article mentions involves keeping an open mind and looking to others for feedback. “When identifying anti-patterns in our code or design, we must keep an open mind and question our assumptions. Sometimes, we may become attached to a solution that required a lot of time and effort, but there might be a better solution out there. To avoid this, it is helpful to seek feedback from others.” As this quote states, it is imperative not to be too attached to a process that you developed or are developing, especially if the time it takes to develop or implement this feature is more than the value that the feature is worth. Another important part of being able to mitigate the harm done by anti-patterns is knowing how to avoid them.

While being able to identify anti-patterns is incredibly important, it is also important that one knows how to prevent their occurrence in the first place. One method of doing so is by stepping back and looking at the greater picture of the project that you are working on. “When working on software projects, it is essential to be aware of common pitfalls that can lead to anti-patterns. One strategy to avoid these pitfalls is to take a step back and consider the larger context of the problem. Understanding the problem in its entirety will help in coming up with a good solution.” Instead of being hyper-focused on one part of a larger project, which could lead to anti-patterns arising in your code, its best to take a step back occasionally to make sure what you are working on is not falling into the traps of anti-patterns. Another method of preventing anti-patterns would be a divide-and-conquer approach to developing features. “Another strategy is to break down large problems into smaller pieces. Doing this can help avoid getting overwhelmed and make it easier to spot issues and inefficiencies.” Using this strategy can be very beneficial because it can allow you to see anti-patterns as they appear in your code.

Article: https://www.baeldung.com/cs/anti-patterns

From the blog CS@Worcester – P. McManus Worcester State CS Blog by patrickmcmanus1 and used with permission of the author. All other rights reserved by the author.

CS343 – Week 4

Through the duration of this class, we have worked a lot with different types of classes, abstract and concrete, as well as interfaces to better design the code. It was not a new concept to me, as I have learned some of the basics to these in prior classes. However, I never truly understood the benefits and the right time to incorporate each. The articles I found give a simple explanation on the distinctions between concrete classes, abstract classes, and interfaces, as well as the correct situations to use them in.

A concrete class, sometimes just referred to as a class, is used to specify any entity. It also can work as a blueprint for all entities with the same attributes. An abstract class and interfaces are similar and was often confusing for me to distinguish the two of them at first. An abstract class will have methods implemented inside the body, but abstract methods will not have the body of the method inside this class. For example, the duck class I was working with for Homework 2 has the abstract class Duck and the abstract method display(). The body of the method is not present in the abstract class because the different concrete classes implementing Duck uses display() to show different messages. An interface only has the method names included for classes to implement with the interface but does not have any body of the methods. This is what partially distinguishes abstract classes from interfaces, as abstract classes can have concrete methods defined in them while interfaces can only have the method names defined. Interfaces are handy when only needing to enforce a contract. Whoever implements this interface will provide an implementation of all the methods. Abstract classes are helpful when only needing partial implementation, which leaves the responsibility of implementing non-useful methods from the class.

The phrase “program to an interface, not an implementation” is new to me and I am starting to make more sense of it. Concrete classes are the actual implementation, interfaces are the contract, and abstract classes are a trade-off between both. Being able to fully program these three structures into the program helps with maintainability, extensibility, and testability. When programming to an interface, you are forced to split the program into subsystems, with each subsystem responsible for certain tasks and having the ability to communicate with each other to complete the whole task. The key to making the program more flexible is focusing the design on what the code is doing rather than how it does it.

I decided to pick this topic for my blog because I had always had a good idea of how to physically write programs to function correctly. However, something that I never focused on before was the structure of the code which can help when needing to develop the program further after initial creation. Most of our time spent in the class so far has been focusing on this concept and it is proving to be very important the more a program continues to develop.

Program to Interface, Not Implementation – Beginner’s Tutorial for Understanding Interface, Abstract Class and Concrete Class – CodeProject

Programming to an Interface – DZone

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.

SW Design Strategy – Interfaces vs. Abstract Classes

An age-old discussion in the computer science and Object-Oriented Programming world is whether/when to implement interfaces or inherit through abstract classes. In these first few weeks of CS-343 we’ve been working on several activities discussing some of the strengths, weaknesses, and differences between interfaces and abstract classes. In the past I’ve worked on some mid-modest sized projects which include both and can think of a few great examples of using each, but I found that I still struggled to understand some of the basic conceptual differences. So while I had a solid grasp on some effective use cases, I didn’t have a very clear idea on how to choose one/the other when in design stages where a lot less may be known about the project and how it may take shape later on.

Interfaces or Abstract Classes is a blog post from 2017 that I came across through web searching which explains some of the key conceptual and strategic differences between abstract classes and interfaces. Author Suhas Chatekar begins by discussing some of the most common responses he has received when asking this question in interviews. Abstract classes are typically preferred if there are suspected to be changes/additions needed later on. Interfaces are considered best when there are likely to be many different definitions for the same inherited methods, or as a possible alternative or substitute in multiple-inheritance in languages which do not support it (like Java/C#). 

Often it’s difficult to verbalize these differences, but this pretty well summarized my understanding. However, these philosophies focus on using interfaces to get around a syntax/language obstacle rather than as a best-case tool and are what Chatekar dubs “futuristic”, in that they rely on a programmer to know how the program is going to turn out longer term at the beginning which is simply unrealistic on a large scale project. Instead, he suggests an approach of considering interfaces as establishing a “can-do” relationship versus abstract classes creating a “is-a” relationship.

In the past and in CS-343, I’ve heard these terms thrown around and attached sometimes, but this post helped me to better understand the value in this approach and line of thinking for project planning. Commonly project components and requirements shift over the course of a project as unexpected needs are identified and addressed which cannot necessarily be planned for, so a futuristic interface-versus-abstract decision process seems likely to fail or be significantly less effective than a simplified approach focused on anticipated “is-a” and “can-do” relationships. One of my first and favorite interface/inheritance example projects simulated a Chess game using Java with a ChessPiece abstract class as well as a PieceAction interface; Regardless of later complications, each piece “is-a” ChessPiece, and “can-do” all PieceAction’s. This approach helps plan for future project events and needs in a more present state of mind, especially in long term projects that may include both.

Source:

Interfaces or Abstract Classes?. I have been asking this question in… | by Suhas Chatekar | Medium

From the blog CS@Worcester – Tech. Worth Talking About by jelbirt and used with permission of the author. All other rights reserved by the author.

The Art of Crafting Web Systems: Unveiling the Front End, Back End, and Data Persistence Layer

In the exciting realm of web development, the successful implementation of web systems hinges on understanding the intricate dance between three core components: the front end, the back end, and the data persistence layer. This blog post aims to dissect these vital components, shedding light on how they collaborate harmoniously to bring web applications to life.

The Front-End Canvas

Imagine the front end as the artist’s canvas, the visual facade of your web application that users interact with directly. It encompasses everything you see and interact with on a website—buttons, forms, navigation menus, and the overall layout. The front end relies on a trio of essential technologies:

  1. HTML (Hypertext Markup Language): HTML acts as the foundation, structuring web pages by defining content and layout.
  2. CSS (Cascading Style Sheets): CSS is the stylistic wizard responsible for the visual appeal, ensuring that the web elements harmonize seamlessly.
  3. JavaScript: JavaScript adds interactivity to the canvas, bringing it to life by creating dynamic elements, managing user input, and facilitating communication with the back end.

The Back-End Engine

Behind the scenes, the back end serves as the powerhouse of your web application. It handles user requests, processes data, interacts with databases, and sends responses. Several technologies and frameworks excel in back-end development:

  1. Node.js: Node.js enables JavaScript to run on the server side, making full-stack development a breeze.
  2. Ruby on Rails: Rails offers a structured framework that simplifies the creation of robust web applications with concise code.

The Data Persistence Layer

No web system is complete without a reliable data persistence layer. This layer manages data storage, retrieval, and efficient data management. It’s home to various types of databases, including:

  1. MySQL: MySQL, a popular relational database, is known for its reliability and is widely used in web applications.

The Synchronized Symphony

These three layers—front end, back end, and data persistence—complement each other to deliver a seamless user experience. When a user interacts with the front end, JavaScript often sends HTTP requests to the back end. The back end processes these requests, interacts with the chosen database to retrieve or store data, and then sends a response back to the front end. JavaScript on the front end dynamically updates the user interface based on this response, creating a responsive and interactive web application.

In Closing

Understanding the synergy between the front end, back end, and data persistence layer is fundamental to web development. These layers work in harmony, much like the instruments in an orchestra, to create the symphony of a fully functional web system. As you embark on your web development journey, remember that mastery of these layers takes time, practice, and a touch of artistry. So, keep coding, keep building, and explore the boundless possibilities of web system implementation.

References:

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

Navigating the Aroma of Code: Unveiling Code Smells and Design Smells

In the vast landscape of software development, there’s an underlying principle that seasoned developers know all too well: code should not only work but should also be maintainable, readable, and scalable. To achieve this, we often find ourselves identifying and addressing something known as “code smells” and their close cousins, “design smells.”

Understanding the Essence

Let’s start with the basics. Code smells are those subtle hints in your codebase that something might be off. They’re like those faint odors in your room that you can’t quite pinpoint but know need attention. These “smells” indicate potential issues that can make your code harder to understand, modify, and extend (Fowler, 1999).

On the other hand, design smells are more like the underlying structural issues in your code that lead to code smells. If code smells are the symptoms, design smells are the root causes (Beck et al., 2002). Identifying and addressing design smells is essential for maintaining a clean and healthy codebase.

Common Code Smells

  1. Long Methods: Code smells often start with overly long methods or functions. When a function becomes a novel, it’s difficult to follow, debug, or modify. Break down long methods into smaller, focused ones for clarity (Fowler, 1999).
  2. Duplicate Code: Repeating the same code in multiple places is a classic smell. It leads to maintenance nightmares since you have to make changes in multiple locations when updates are needed (Fowler, 1999).
  3. Large Classes: Just as long methods can be problematic, large classes or modules can become unwieldy. Split them into smaller, more cohesive units (Fowler, 1999).
  4. Magic Numbers: Using hard-coded numbers without context is a recipe for confusion. Replace them with named constants or variables (Fowler, 1999).

The Path to Design Smells

Design smells often stem from issues in the overall architecture and structure of your code. Some common design smells include:

  1. God Class: When one class knows too much and does too much, it becomes a “God Class.” This violates the Single Responsibility Principle (SRP) and makes the code less modular (Fowler, 1999).
  2. Spaghetti Code: Unstructured and tangled code that’s hard to follow is like a bowl of spaghetti. It usually arises from poor planning and lack of separation of concerns (Kerievsky, 2014).
  3. Circular Dependencies: When modules or classes depend on each other in a circular manner, it can lead to maintenance challenges and hinder code reusability (Fowler, 1999).

The Importance of Addressing Smells

Ignoring code and design smells is like letting that mysterious odor in your room linger; it won’t get better on its own. Instead, it can worsen over time and create a bigger mess to clean up (Fowler, 1999).

Addressing code smells and design smells early in the development process can save time, reduce bugs, and make your codebase more maintainable. It’s like opening the window to let fresh air in; your code will become more pleasant to work with (Fowler, 1999).

Conclusion

In the world of software development, understanding and recognizing code smells and design smells is essential for writing clean, maintainable, and efficient code (Fowler, 1999). Just as identifying that peculiar odor in your room can lead to a more comfortable living space, addressing these smells in your code can lead to a more productive and enjoyable development experience.

So, as you embark on your coding journey, keep your nose keen, and don’t hesitate to refactor and improve your code whenever you detect those telltale aromas of code and design smells. Your future self—and your fellow developers—will thank you.

References:

  1. Fowler, M. (1999). Refactoring: Improving the Design of Existing Code.
  2. Beck, K., et al. (2002). Extreme Programming Explained: Embrace Change.
  3. Kerievsky, J. (2014). Refactoring to Patterns.

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

Week of October 2, 2023

https://refactoring.guru/design-patterns/singleton

This week, I wanted to a find a source relating to software design and architectures. I’ve been curious about what I would need to know so I could write more robust and efficient code. One aspect of improving my code would be knowing how best to preserve available system memory and perform whatever tasks I need to within as few CPU cycles as I can. If my program is creating multiple instances of a class that are all doing the same thing, my code would be consuming more system resources than if I had one instance of a class that could be accessed by other parts of my code. The Singleton design pattern seeks to preserve memory consumption by utilizing a single static instance of a class that may be globally referenced from the rest of the program. To properly implement the Singleton, the constructor for your Singleton instance should be static and private. To get the instance, you would also need a public static creation method.

My homework for this week involves refactoring a class into the Singleton pattern, so I was especially interested in learning about it. I found this blog called The Refactoring Guru, and a post explaining the implementation of the Singleton, as well as the pros and cons from a design perspective. The Singleton design is useful when a program needs global access to a class, like when a program has a single attached database. The drawbacks of the Singleton approach, though, are that it does too many things at once in violation of the Single Responsibility Principle, and that it may compromise your program’s security because of a crucial class being accessed as a global variable.

The final paragraph of the blog post makes some comparisons between the Singleton design and two other software design patterns, Façade and Flyweight. Façade is a design pattern of constructing a simple user interface with a complicated backend. This design pattern offers a sort of “black box” functionality to users, having a simple frontend to interact with without the need to inform users about the inner implementations of the software. The practical example given for a Façade software design is a video encoding service that accepts video files from the user as input and returns the same file encoded in a new file format. The user would only need to interact with the function that accepts a file and a desired file type as parameters, without needing to access the methods within the program that perform operations on the input file.

This blog includes helpful illustrations and pseudocode to explain multiple different software design patterns. I’ve been needing more resources on broader software structure and design rather than individual blocks of code, and I’m happy that I found this website.

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.