Category Archives: CS-343

Adhering to the Law of Demeter

Also known as the Principle of Least Knowledge, the Law of Demeter states that objects should avoid accessing data and methods that belong in other classes and instead, only interact with its immediate dependencies (Baeldung).

When used with Object-Programming languages, the goal of the Law of Demeter is to make the components of a program less dependent on each other, loosely coupled, and therefore easier to manage and scale.

There are five rules to the Law of Demeter:

  1. The first states that methods should only call methods that belong to their same class. It is not recommended for a method in class X, for example, to call on another method in class Y.
  2. The second rule expands on the first to say that methods of a class should only call methods that belong to the objects created by that class. For example, a method X of a class Z should only call methods of an object created by method X.
  3. The third rule states that a method should only ever interact with an object when passed to it as an argument. There should be no direct access to the object within the method itself.
  4. The fourth rule allows the method of a class to invoke the method of a class given that it is an instance variable of the same class. For example, method X of class C is allowed to call the method of an object held as an instance variable of C.
  5. The fifth rule is similar to the fourth rule except it states that the method of a class is able to call the method of a static field in that same class, similar to a method of an object of the same class.

When these rules of the Law of Demeter are applied, they help prevent code from becoming tightly coupled, meaning that they cannot operate independently. However, there are some exceptions to certain cases such as for chain calling, fluent APIs, or working with data structures. An experienced programmer will know when and how to effectively apply the law of Demeter.

While refactoring the code for one of my research projects, I had practiced to apply the GRASP principles to the new design. For another project that I am refactoring, now that I am more comfortable with the GRASP principle, I will focus more on applying the law of Demeter to make sure my code is not tightly coupled. This means code that is less fragile, scalable, and easier to manage.

Source: https://www.baeldung.com/java-demeter-law

From the blog Stories by Namson Nguyen on Medium by Namson Nguyen and used with permission of the author. All other rights reserved by the author.

api uses

Starting the Docker service also starts the Docker Daemon. However, if you receive the “Cannot connect to the Docker daemon” error, the daemon may have failed to initiate.

Use the following command to run the daemon manually:

From the blog CS@Worcester – Andres Ovalles by ergonutt and used with permission of the author. All other rights reserved by the author.

Inversion of Control

Inversion of control is a software principle that asserts a program can benefit in terms of testability and usability if the management of an application’s flow is transferred to a different part of the program. I.O.C’s framework takes the management of an application’s implementation away from the developer. When interactions require custom business logic, the I.O.C framework will use the code provided by the developer. This is the “inversion” point of the inversion of control design principle. The most common application for Inversion of control is Java servers faces. I.O.C frameworks implement low-level and problem-prone activities, it allows the developer to focus on custom business logic instead of tedious tasks.  The one thing about inversion of control is that it can confuse what qualifies as an I.O.C and what doesn’t. Some examples of inversion of control are event-based user interfaces, shared cache, and comprehension framework—the range of development changes that qualify as I.O.C contributes to the term. I.O.C is a principle, not a design pattern- the implementation depends on the developer. I.O.C just provides high-level guidelines. Inversion of control and dependency injection are usually used interchangeably. Dependency injection is one implementation of I.O.C., it’s a technique that allows objects to be separated from other objects that they depend on.

Dependency injection suggests that instead of making an instance of class b into class a using the new operation, the object of class b should be placed into class a using one of these methods constructor injection, setter injection, and interface injection. Another example of implementation in I.O.C is the spring framework. That contains instances and manages the lifecycle of the objects in the program. The user in the configuration file provides information that relates to what objects and dependencies are used by the application like Java code. The benefits of Inversion of control are that it makes the application easier to test and maintain, reduces the amount of application code, and decreases the coupling between classes. Inversion of control helps make your code more readable because of the absence of some components. At the end of the day, I.O.C is a design pattern that is very useful for software development and lets us know when action needs to be taken when something happens in our system.

https://www.theserverside.com/definition/inversion-of-control-IoC

https://www.educative.io/answers/what-is-inversion-of-control

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

From Learning to Doing

This week I was searching for an article to write about and I stumbled upon an article from Codecademy sharing the story of Juan Paredes, a Full-Stack Engineer from Mexico. The article is an interview of sorts where Juan has responded to prompts related to his journey from a Call Center Supervisor to a Full-Stack Engineer.

Juan covers how exactly he got into software engineering. When first moving to Mexicali, Mexico he got a job as a call center specialist. After 3 years Juan was promoted to Operations supervisor where at this point he decided to expand on his love for computers and wanted to start learning how to code through a free course on Codecademy.

After completing the free course, Juan decided to pay for a subscription and before Juan was completed with his first paid course, he was able to find an entry-level developer position. After figuring out that software engineering is what he truly wants to do, he also started attending the Mexicali Institute of Technology and is currently studying to obtain a degree in Software Engineering.

Juan also talks about how limited time and a pay cut made things temporarily more difficult but between his passion and determination, Juan continues to learn and progress.

When the article was created, Juan had just found a job with better pay and benefits than his first position and continues to progress forward in the software field.

Juan finishes off his remarks by recognizing the importance of organization and being open to learning new things as traits that will carry you far in the field. With organization, one can more easily find how to and be able to implement changes and by keeping an open mind you may learn things that while not valuable at the present, could become of great use in days, weeks, or months later on.

After reading this article I wanted to share and reflect upon it since I could relate to Juan. I too discovered my interest in programming through another medium of computers, however mine was video games. I started my journey by wanting to learn how to script in Lua for Garry’s mod addons and after that, I gradually kept learning more about coding. I never saw it as more than a hobby at the time, but here I am today almost finished with my Bachelor’s in Computer Science and preparing to join the workforce soon. Juan’s story serves as a reminder that through determination and perseverance, I can learn and do whatever I want within the extensive computer science field after obtaining my degree. It may take time, but in the end, the hard work will pay off regardless of how hard it may be or how much I would want to give up.

Article Link: https://www.codecademy.com/resources/blog/from-call-center-sales-representative-to-full-stack-engineer/

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.

Anti-Patterns ≠ Clean Code

Take 2

Well here we are, back again talking about clean code. I thought it would only be fair to introduce you to its evil counter part. Now that I really think about it, I really must be goo at these blogs because I am giving away the secret recipe to the perfect code. If you know how to write clean code BUT also know how to avoid bad patterns thats the ulntimate duo, nothing should stop you!

What is Anti-Pattern

it is how NOT to solve recurring problems in your code. Anti-patterns are considered bad software design practices, and they are typically ineffective or obscure fixes. They can lead to issues such as technical debt, where suboptimal code must be addressed and corrected later.

  1. Spaghetti Code:
    • Description: Code with little to no structure, making it difficult to follow.
    • Issues: Maintenance nightmare, challenging to add new functionality, and prone to breaking existing code.
  2. Golden Hammer:
    • Description: Overreliance on a specific architectural pattern or tool.
    • Issues: May lead to performance issues, difficulty adapting to different problems or languages, and inhibits learning and exploration.
  3. Boat Anchor:
    • Description: Leaving unnecessary or obsolete code in the codebase with the assumption that it might be needed later.
    • Issues: Causes confusion for developers, longer build times, and the risk of inadvertently activating obsolete code in production.

Why we might use it still

  1. Prototyping or Rapid Development:
  • In the early stages of prototyping or rapid development, the primary focus might be on quickly testing ideas or demonstrating concepts. In such cases, developers might use shortcuts that resemble anti-patterns to expedite the process. However, it’s crucial to revisit and refactor the code for production use.

Anti-pattern is a practice or solution that may seem like a good idea at first but, in reality, is counterproductive and can result in negative consequences for the software development process. It’s a term used to caution against common pitfalls and encourage developers to adopt best practices for creating maintainable, efficient, and effective code.

While there may be rare instances where the use of anti-patterns is justified, such as in prototyping, rapid development, or within legacy systems, it’s essential to recognize that intentional use of anti-patterns comes with inherent risks. These include technical debt, reduced code quality, and challenges in maintaining and scaling the software. I still encourage developers to prioritize clean code above all else.

From the blog CS@Worcester – CS: Start to Finish by mrjfatal and used with permission of the author. All other rights reserved by the author.

Code Documentation 101

Tommorow, Not Today

As with many classes, topics, and projects I have been a part of for the last few years, I see a consistent pattern. The unwavering focus on what’s going on in the present and never connecting the dots on how something might benefit me in the future.

Code documentation is just one of the many examples I could come up with to further my point. Up until now, all my work has followed the motto of “me, myself, and I,” failing to see that in the future that won’t be the case. Eventually, everyone will find themselves a part of a team, and there is nothing worse than an amateur teammate. Let’s take a deeper look into code documentation and why it will eventually be an asset to not just you but also your future teammates.

Type of Code Documentation

Internal Code Documentation: Intended for developers inside the organization.

  • Process Documentation: Provides high-level information like product requirements, roadmaps, notes, and reports.
  • Developer Documentation: Provides detailed instructions for developers and staff for building, testing, deploying, or maintaining the software.

External Code Documentation: Intended for developers outside the organization who integrate with the product or need to understand its code.

  • External Developer Documentation: Provides essential instructions for using source code, integrating with a product, and leveraging developer interfaces like APIs and CLIs.
  • Enterprise Documentation: Furnishes information for IT staff involved in software deployment, covering hardware requirements, sizing, operational needs, and maintenance guidelines.
  • Usage Documentation: Guides non-developer users on product utilization without relying on programmatic interfaces. Describes main functionalities within the product’s UI.
  • Just-in-Time Documentation: Supports developers as needed, often in the form of knowledge base articles, FAQ pages, or blog posts, added in response to new features or requirements.

Low-Level or Inline Documentation: Resides within the source code and explains details of specific code parts in isolation, such as the purpose of certain functions and arguments.

High-Level Documentation: Describes the architecture, design principles, implementation guidelines, or other broader concerns.

Walkthrough Documentation: Describes flows, patterns, and other important parts of the codebase, especially for developers who need to contribute to the code.

Food for Thought

Documentation might seem straightforward, but there are some issues that must be considered whenever starting a new document.

  • Knowing Your Audience: Depending on why/who you are writing your documentation for, you must consider their level of understanding when it comes to your subject.
  • Updating Documentation: It is very easy to push changes to your software and forget to also push changes to documentation. This starts a cycle with co-workers where the documentation falls behind and becomes uncomprehensible.

Tommorow

Embracing comprehensive code documentation is not just a practice for today but an investment in our collective future. As we transition from individual contributors to collaborative team members, the value of clear, well-maintained documentation becomes vital to future projects.

Source – https://swimm.io/learn/code-documentation/code-documentation-benefits-challenges-and-tips-for-success

From the blog CS@Worcester – CS: Start to Finish by mrjfatal and used with permission of the author. All other rights reserved by the author.

software design patterns

We’ve gone over a couple of design patterns in class this semester. Some that come to mind are the singleton and factory patterns, both of the creational variety. This latter half has been more focused on practical applications of software construction, taking a look into the Thea’s Pantry system that uses a microservices approach, but earlier on we were working with design decisionmaking and approaches.

A software desing pattern is a reusable solution to a problem that occurs often. The three main types of design patterns are creational, structural and behavioral. This is all well and good, but what do these types entail? I found this blog post from NetSolutions regarding the subject, and it gives a brief explanation of each as well as some examples.

Creational design patterns are solutions for the creation of objects and how they are used. The aforementioned singleton and factory patterns are creational because they dictate the way that objects are meant to be created based on the circumstances surrounding it. Singleton ensures a single instance of an object that can be called, while the factory is a sort of constructor of objects that utilizes an interface to form an object from sub-classes.

Structural design patterns relate to object composition to form better flexibility when working on a large-scale project. For example, an adpater is a structural design pattern that allows for incompatible interfaces to work together, creating greater flexibility in the program. The facade pattern is a sort of application of encapsulation and abstraction, allowing for the hiding of complexity with an interface, making it easier to work with.

Behavioral design patterns deal with separate objects and the way they share responsibility and communicate. The strategy design pattern is an example of this, where algorithms are put into a family where each algorithm is only called when it needs to be called, increasing efficiency. The observer pattern links one object to many dependents, notifying the observer object whenever any depedent has experienced any event.

It seems important to have these tools in your belt, considering that many of the problems that these design patterns solve occur fairly regularly even when developing different pieces of software. The one thing I would consider being wary of is using software design patterns at all times when you may not need it. For example, the factory pattern is best used when working on a fairly large project, but is not necessary at a smaller scale. Of course, when a project goes from small to large, a refactor may be called for, but perhaps the factory pattern is not the best tool for the job, it’s instead a builder or prototype. There is no one-size-fits-all solution, and so it’s also a skill to know when and how to use patterns and not just apply them randomly.

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.

Suggested Standards for (basic) REST API Calls

In the past few weeks, we’ve finished the CS-343 semester focusing on designing/implementing REST API calls and interacting with back- and front-ends. During one of our classes, I recall a discussion about the fact that there are no unified across-industry “best practices” for writing API’s. Specific API structures and rules are common within teams but can vary from organization to organization, however there are some general habits and strategies. So I decided to do some searching and focused on a blog post on the website for Swagger, the REST API view/interaction software we’ve been using in class: Best Practices in API Design.

The post discusses some general best practices on creating consistent, well-designed API’s by focusing on three key characteristics: 

  1. Being easy to read, understand and work with
  2. Being hard to misuse, and in turn more intuitive for users
  3. Completeness and Conciseness – something which the post acknowledges frequently happens over time as developers build on top of existing APIs

Alongside some other basics on CRUD operations and how they correlate to standard REST API calls (get, post etc.), the post also dives into practices for writing effective call response messages. The codes for responses should follow the HTTP standards, where client-side errors return 400-level (4xx) codes versus server-side errors return 500-level and successful calls return 200-level. 

Arguably most important is providing thorough and clear explanations in response messages. For error responses, this entails providing detailed messages describing the error that occurred and suggestions/tips to address and debug it. As a part of this, it’s worth considering putting an example of a successful call to show proper syntax and passed parameters – handholding users will pay off with smoother API interactions long term. To reinforce this, the blog post recommends providing examples for all possible GET responses to demonstrate successful data access calls.

While specific implementations will vary by project/system, these are some good strategies and habits to keep in mind. The importance of providing examples for each individual GET response really sticks out and hits home for me. I can imagine with more complex systems and calls that may contain various request, query or other parameters it could quickly become confusing for users to navigate and access information they need. It seems worthwhile to also provide an example of a successful call in the error response for some specific situations, such as an Error 400 – Malformed Requested → providing an example successful request. 

Below, you’ll also find a link to a “glossary” of REST API parameters with explanations on their purpose and uses – a resource I also recently came across and have been finding valuable. If you have any other suggested “best practices” to keep in mind when designing REST API calls, please let me know in a reply or E-Mail.

  1. Blog Post: https://swagger.io/resources/articles/best-practices-in-api-design/
  2. Parameter Glossary: https://rapidapi.com/blog/api-glossary/parameters/

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 13: CS-343

Anti-Patterns

Anti-Patterns are “imperfect” fixes that may seem like they solve a problem, but over time, can lead to more problems where using anti-patterns are more inconvenient than not. Because anti-patterns cause problems over time, teams are forced to go back and fix them which lead to higher costs and delayed release schedule.

Types of Anti-Patterns

Spaghetti Code

Spaghetti code refers to the logical structure of the code resembling a plate of spaghetti, meaning it is unorganized and confusing. Spaghetti code usually occurs when a developer starts a project without putting much thought into the organization of the code. Although the end product may work, adding functionality may increase fragility. Using the spaghetti analogy, adding more code would be like adding more spaghetti leading to an even larger tangled mess.

Golden Hammer

Golden Hammer refers to one tool being the solution to all problems. A developer may have used a well designed piece of code to solve previous problems, but relies too heavily on it by trying to use the code for problems that do not necessarily belong. Forcing code where it may not belong can lead to spaghetti code. The Golden Hammer concept can be thought of as trying to cut a piece of wood with a hammer.

Boat Anchor

The Boat Anchor anti-pattern occurs when a piece of code is left in the code base, so it can be saved for later use. Although the code may not make sense for the program, the thought process of saving the code is if the code is needed later it can be turned on and off with comments. Some may think because a piece of code is commented out, there is no harm in leaving it. However leaving unnecessary code can lead other developers confused about what the code is intended for and over time may slow down build times. Turning the code back on may also break the code if changes were made to the point where the saved code may no longer be compatible.

God Object

A God Object is an object or a class that has too much responsibility for the program. This violates the single responsibility principle, as every object and class should only be responsible for one single part of the program. For example, there is a customer ID class responsible for the customer’s first and last name, transactions, and more. Rather than the customer ID class manage all those details, better practice would be to have customer ID be responsible for the customer’s name while a separate class is created for transactions.

Reflection

This resource was chosen because it explains what anti-patterns are, why they are bad, and listed common types of anti patterns. The article was informative as I realized I am guilty of utilizing many of these anti patterns such as spaghetti code and god object. After reading this article I am now aware of these anti patterns, and will be more mindful to not use them in the future.

Resources:

https://www.lucidchart.com/blog/what-are-software-anti-patterns

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

Backend Unveiled: A Historical Journey from Server Stumbles to Network Pioneers

The Roots of Today’s Modern Backend Engineering Practices: https://blog.pragmaticengineer.com/the-roots-of-modern-backend-engineering-practices/

Summary:
In this blog post, we explore the evolution of modern backend practices through the lens of Joshua Burgin, an industry veteran with a rich background in backend development. The journey begins with his early days at Amazon, where accidental outages led to valuable lessons in observability and robust systems. We then travel back to 1969, witnessing the birth of ARPANET, a pioneering project that laid the groundwork for today’s distributed networks. The narrative continues into the 1980s, marking the rise of the internet and web-based computing, crucial milestones that shaped the challenges and solutions of backend development.

Reason for Selection:
This resource was chosen for its deep exploration of the historical roots of modern backend engineering practices. Joshua Burgin’s firsthand experiences, coupled with insights into the development of ARPANET and the internet, provide a holistic view of the challenges, innovations, and pivotal moments that have shaped the backend landscape.

Comments on Content:
Joshua’s recounting of the early days at Amazon offers a vivid picture of the challenges faced by developers in the late ’90s. The simplicity of tools like shell scripting and Perl, coupled with the manual deployment processes, highlights the stark contrast to today’s sophisticated backend practices. The emphasis on observability and the significance of monitoring, learned through real-world incidents, resonates with the importance of these aspects in contemporary development.

The exploration of ARPANET’s birth showcases the pioneering spirit of the engineers who laid the foundation for distributed networks. The introduction of packet switching and its impact on fault tolerance and high availability provides valuable context for current backend practices. Understanding these early challenges fosters an appreciation for the sophisticated tools available today.

As the narrative transitions to the internet’s rise in the 1980s, the challenges faced by businesses like Amazon in scaling infrastructure and serving international audiences become apparent. The change from text-based interfaces to graphical browsers reflects the transformative power of user-friendly technologies, a lesson relevant in today’s user-centric development approaches.

Personal Reflection:
This resource has deepened my understanding of the roots of backend engineering, emphasizing the iterative nature of progress in technology. The anecdotes from Joshua’s career underscore the importance of learning from failures and adapting to the evolving landscape. The historical context provided by ARPANET and the internet’s emergence serves as a reminder of the continuous innovation that defines backend development.

Moving forward, I plan to apply the lessons on observability and robust system design in my own projects. The historical insights have reinforced the idea that every complex system today stands on the lessons from earlier times, encouraging a forward-looking approach that considers the evolution of technology.

From the blog CS@Worcester – Site Title by rkaranja1002 and used with permission of the author. All other rights reserved by the author.