Author Archives: atruong1

Rest APIs: The Anatomy of a Request

Rest, an acronym for Representational State Transfer, is a type of API for web services that have a client-server architecture where clients request for data and servers return data in plain text formats, such as JSON, XML, and YAML. In my software engineering course, designing Rest API requests was the most difficult challenge I faced because I did not understand the parts of a request and their purposes. Because understanding a request’s components is fundamental to designing Rest APIs, the goal of this post is to explore the parts of a request. To help me achieve my goal, I will be using the article, “Rest API: the basics,” which explains the three components of a request: its method, uniform resource locator (URL), and body.

The request method is a procedure a client wants to make. The available methods include GET, PUT, POST, and DELETE. Because they are the same methods used by computers to download pages (or hypertext documents) from a web server, they are called Hypertext Transfer Protocol (HTTP) methods. The GET method is used to get one or more items from a server; the PUT method is used to update an item in a server; the POST method is used to create and add an item to a server; the DELETE method is used to remove an item from a server. Given the methods, a client can make requests to only create, read, update, or delete data.

The URL is an address to a resource, a unit of an item, in a server. The URL is made up of an endpoint and path. The endpoint is a reference to a web server, whereas the path is the identifier of the resource in the server. Given the URL, “https://twitter.com/justinbieber,” the endpoint is “https://twitter.com/,” and the path is “/justinbieber.” The endpoint is the reference to Twitter’s server and the path is the identifier of Bieber’s Twitter page.

The body is an optional section where a client specifies the data it wants to send to a server. It is only used with POST and PUT methods because the server would need data to update (put) or create (post) items. The format of the body must be in the format of the response. In other words, if the server returns items in JSON format, the client must input data in JSON format.

To bring my understanding full circle, I will be breaking down and interpreting the components of a request I defined and called for a food pantry software in my course.  The request is

“GET http://localhost:10001/orders/61b16887ca02e000073ceabc.” I used the GET method because the request is intended to retrieve all orders of a given ID from an Orders database. “http://localhost:10001,” is the reference to my webserver, which I hosted on my local computer. “/orders/61b16887ca02e000073ceabc,” is the identifier for specific type of order in the database.  The components make up the request to fetch all orders of a given ID.


https://towardsdatascience.com/rest-api-the-basics-d91859537c9d

From the blog CS@WORCESTER – Andy Truong's Blog by atruong1 and used with permission of the author. All other rights reserved by the author.

Application Programmable Interfaces (APIs): What Are They?

For this week’s post, I am refining my definition of an API and exploring the reasons why an API might be used. When I was learning to program in Java in CS140, the course textbook described the Java API as a library of prewritten code programmers can use to add functionality to their programs. Because the textbook described an API as a library, I defined APIs as libraries of reusable code. When CS343 reintroduced me to APIs, my instructor described an API as a link between two applications. Because his definition of API conflicts with my definition of API, I feel as though my knowledge about APIs is unsound. To polish my understanding, my post’s goal is to explore APIs and the reasons they are used. To help me achieve my goal, I will be reflecting and adding to MuleSoft’s article, “What is an API? (Application Programmable Interface)”

An API is how two applications can share information. To explain an API, Mulesoft uses an analogy; Mulesoft states, in a restaurant system, a waiter is an API for a customer and the kitchen. In other words, the waiter is how a customer can communicate his or her order to the kitchen. Mulesoft then transitions to APIs in software development by introducing flight search applications, such as Priceline, Kayak, and Expedia. The flight search applications aggregate information from various airlines, including Worcester Regional Airport and Boston Logan International Airport, by using APIs. In other words, flight search applications collect flight information from airline applications through an API. Both examples show that APIs are used to share data.

While Mulesoft explores only one reason why developers use APIs, developers use APIs to also

hide complexity. Ride-sharing applications, such as Uber and Lyft, are examples of how APIs are used to hide complexity. They use the Google Maps API to display a map and generate routes for drivers and riders. I know they use the Google Maps API because after installing Uber or Lyft, the application asks for permission to use Google Maps. The API hides complexity because Uber and Lyft developers do not need to create a map and define pathing algorithms. Uber and Lyft show that developers can focus on building upon the capabilities of another application by hiding complexity.

A third reason why developers use APIs is to extend functionality. Online stores that accept Paypal payments, such as BestBuy, eBay, and Etsy, are examples of how APIs are used to extend functionality. They use Paypal’s API to provide a Paypal login form and collect money. The API gives online stores the ability to accept Paypal payments. By adding functionality, end-users will have multiple payment options.

Returning to the conflict that inspired this post, the Java API is a library and an API. It is a library because it provides reusable code. It is an API because it allows two programs to communicate with one another. The library is simply part of the API.


https://www.mulesoft.com/resources/api/what-is-an-api

From the blog CS@WORCESTER – Andy Truong's Blog by atruong1 and used with permission of the author. All other rights reserved by the author.

Docker: The Differences Between a Dockerfile, Image, and Container

Docker is a program used to package applications and their dependencies into bundles that can run on any computer. A running instance of the bundle is a container. Docker containers help developers build software by isolating applications, sandboxing projects, and guaranteeing running software. To have a docker container, one needs to write a Dockerfile, build it into an image, and run the image. When I was learning the process, my instructor explained the process and terms by using only an analogy. He compared them to the process of how source files became executables, and then running processes.  Because analogies only help understand concepts (not define them), the goal of this post is to define Dockerfiles, images, and containers as well as their relationships. To achieve the goal, I will be using information from the article, “Differences Between Docker Images and Containers,” written by Eugen Baeldong, an author who has written about software development extensively. His article differentiates Docker images from containers.

The Dockerfile is a text file that contains instructions on how to find, install, and configure an application and its dependencies. In the same way an embryo is a baby at the first stage of development, a Dockerfile is a container at the first stage of development. Some commands that can be used to create instructions are RUN and COPY. RUN is used to install a package or application and COPY is used to copy files and directories from one location to another. With the commands, instructions are created. The set of instructions tell a computer how to find and install the applications and its dependencies.

When a computer executes the instructions in a Dockerfile, an image is built. According to Baeldong, an image is a template for creating the environment one wants. In other words, it is a snapshot of a system one wants. Returning to the baby analogy, an image is a container at the second stage of development in the same way a fetus is a baby at the second stage of development.  I imagine an image as one’s desktop environment. The icons in the environment represent the application and its dependencies in a dormant state. The application is not running yet in the same way desktop applications do not run until one double-clicks their icons.

When a computer runs an image, a container is created. A container is an environment where an application and its dependencies are running. The application in the container is independent from the applications on the computer. In other words, the contents inside a container and one’s computer are unaffected by one another. I imagine it as a computer inside a computer; however, the second computer will not have a graphical interface because it is not necessary for an application to run.


https://www.baeldung.com/ops/docker-images-vs-containers

From the blog CS@WORCESTER – Andy Truong's Blog by atruong1 and used with permission of the author. All other rights reserved by the author.

Is Unclean Code Technical Debt?

When my instructor introduced technical debt, he described it as poor design choices that delay the productivity of a development team. When I was learning about how unclean code can slow down the software development process, I asked myself, “Is unclean code technical debt?” To answer the question, I am going to explore and compare the meanings and consequences of unclean code and technical debt. I will be using chapter 1 of Clean Code, written by Robert C. Martin to support the discussion. Chapter 1 explores the meaning of clean code and its value.

Unclean code is code that cannot be read and enhanced by a developer other than the original developer. Some qualities of unclean code include uninformative names, redundant comments, and multi-purpose functions. Some reasons for unclean code may include making a deadline and having inadequate skills. Unclean code is consequential because it slows down the development process. When code becomes unclean, it becomes difficult to read. When it is difficult to read, it becomes to develop.  Martin reinforces the value of clean code by talking about how unclean code killed a company in the 80s: “As they added more and more features, the code got worse and worse until they simply could not manage it any longer. It was bad code that brought the company down.” In other words, bad code tempts bad code and as bad code piles up, the application eventually becomes unusable, unmaintainable, and not worth fixing.  Unclean code hampers the capacity of an application to be developed.

Technical debt is the time a developer needs to use to refactor the code of a piece of functionality from a previous release because the functionality was implemented hurriedly. In software development, developers may deliver an application faster by using a convenient course of action to implement a piece of functionality. When they tell themselves they are going to refactor the code and add even more functionalities in the next release, they are putting themselves in technical debt. The debt becomes consequential when it is never paid. If developers do not pay the debt by refactoring the code, it may be difficult to understand. The lack of understanding may tempt developers to pile on the mess with unclean code and unintuitive implementations. As the mess grows, the application may become unusable, unmaintainable, and not worth fixing. Technical debt hampers the capacity of an application to be developed.

While unclean code functions like technical debt, I do not think unclean code is technical debt. Unclean code describes code, whereas technical debt describes the extra time a developer needs to use to refactor code. I think the two concepts have a cause-and-effect relationship, where unclean code is the cause and technical debt is the effect. The loss of productive time from unclean code may sway teams to take shortcuts. Understanding unclean code as a cause of technical debt will encourage me to become more aware of the way I write my code.


Martin, Robert Cecil. “Chapter 1: Clean Code.” Clean Code, Apogeo, Milano, 2018, pp. 33–46.

From the blog CS@WORCESTER – Andy Truong's Blog by atruong1 and used with permission of the author. All other rights reserved by the author.

Virtual Machines vs. Containers

Assume a software developer who has a Windows computer creates an application and sends it to a tester who has an Apple computer. Do you think the application would work on the tester’s computer? The application may not work because it may be runnable on only Windows computers. The developer should solve the potential problem by using virtual machines and containers, ways of packaging applications into self-sufficient units that can run on any computer. When I was learning how to use Docker, a program used to create and run containers, my instructor often compared it to a virtual machine. To make sense of the comparisons, the goal of this post is to define the relationship between virtual machines and containers. To achieve the goal, I will be using the information from Preethi Kasireddy’s article, ‘A Beginner-Friendly Introduction to Containers, VMs, and Docker” which differentiates virtual machines from containers by architecture.

A virtual machine is an emulation of a computer. It is run on physical computers, called host machines, using a hypervisor, a program that creates and runs virtual machines. A few commonly used hypervisors are VMware, Hyper-V, and VirtualBox. For every virtual machine, the hypervisor provides an operating system, application, and assortment of dependencies. When a virtual machine is running, it depends on its operating system to manage how the application uses a partition of the host system’s resources. Each virtual machine’s operating system then depends on the host machine’s operating system to manage how the host system’s resources are partitioned.

A container is an executable package with an application and the application’s dependencies. They run on physical computers called host machines, using a containerization application, a program that creates and runs containers. As of today, the most used containerization application is Docker. For every container, the containerization application provides an application and assortment of dependencies. Because every container does not have a separate operating system, one can think of it as a virtual machine without a separate operating system. When a container is running, it depends on the host machine’s operating system to manage how the host system’s resources are used.

When I think about the architectural differences between a virtual machine and a container, I think about a house and an apartment respectively. A house represents a virtual machine because each family has their own set of utilities in the same way each virtual machine has an independent operating system. An apartment represents a container because multiple families share the same set of utilities in the same way multiple containers share the host system’s operating system.

If I continue to pursue a career as a software engineer, my understanding of virtual machines and containers will help me decide how to deploy my applications. If I want my application to efficiently use operating system resources, I should consider deploying it with a container.  If I want to deploy a system, I should consider deploying it with a virtual machine.


https://www.freecodecamp.org/news/a-beginner-friendly-introduction-to-containers-vms-and-docker-79a9e3e119b/

From the blog CS@WORCESTER – Andy Truong's Blog by atruong1 and used with permission of the author. All other rights reserved by the author.

Unified Modeling Language (UML): Class Diagram Relationships

The Unified Modeling Language (UML) is a standard for diagramming the design of a computer program. UML class diagrams illustrate the classes and relationships of an object-oriented program. The five fundamental class relationships are dependency, aggregation, composition, inheritance, and realization. When my professor introduced UML, he provided instruction on inheritance and realization. Because an understanding of the five relationships is essential to reading and building UML class diagrams, the goal of this post is to familiarize myself with dependency, aggregation, and composition as well as their applications. To achieve the goal, I will be reflecting and adding to the blog, “Association vs. Dependency vs. Aggregation vs. Composition,” written by Niraj Bhatt, an enterprise architect at Advent eModal. In the post, Bhatt defines and applies the relationships.

Dependency is a relationship between two classes where one class uses the object of another class as a parameter of a method. One can represent it by drawing a dotted arrow from the user class to the class being used. Bhatt exemplifies the relationship in a program that simulates a turn-based game. The program acquires a Player class with a TakeTurn method that expects a Die object. Bhatt’s example is effective because, in many turn-based games, a player uses a die during his or her turn.

Aggregation is a relationship between two classes where one class owns the object of another class as an attribute. If an instance of the owner class ceases to exist, the object of the other class would still exist. One can represent it by drawing a line with a hollow diamond from the owner class to the class being owned. Because Bhatt exemplifies the relationship in an unfamiliar type of game, I will be providing another example. Another application of the relationship is in a course management system where the Course class owns Student objects. The application is effective because students will exist when courses do not.

Composition is a relationship between two classes where one class needs to have an object of another class as an attribute. If an instance of the former ceases to exist, the object of the latter class would cease to exist too. One can represent it by drawing a line with a filled diamond from the owner class to the class being owned. Because Bhatt exemplifies the relationship in an unfamiliar type of game, I will be providing another example. An application of the relationship is in an online shopping system where the Customer class has Order objects. The application is effective because orders would not exist without customers.

If I continue to pursue a career as a software engineer, my newfound understanding of class relationships will help me carry out my responsibilities. Many companies use UML to illustrate their software systems. I may need to apply the relationships to blueprint software or understand them in existing software to implement new features.


From the blog CS@WORCESTER – Andy Truong's Blog by atruong1 and used with permission of the author. All other rights reserved by the author.

The Four Principles of Object-Oriented Design

A programming language supports object-oriented design when it contains features that allow programmers to apply four principles: abstraction, encapsulation, polymorphism, and inheritance. When my class was reviewing the principles, I realized we were struggling to define and provide real-world examples of them. Because an understanding of the principles is fundamental to applying them, the goal of this post is to review and provide real-world examples of them. To review the principles, I will be reflecting and adding onto ParTech’s article, “Basic Principles of Object-Oriented Programming,” which defines and describes the principles.

Abstraction is the process of packing details of a real-world phenomenon into a simplified representation. ParTech describes the process of making coffee with a machine as an example of abstraction: “You use a button defined interface to make coffee, without needing to worry about the internal working of a machine.” In other words, a coffee machine’s button hides (or abstracts) the science the machine carries out to make coffee. A button on a coffee machine is an effective example because we only need to know what button to press to make coffee rather than the machine’s internal systems, such as its circuitry and fluid transfer apparatus.

Encapsulation is the process of packing data and operations that manipulate the data into objects.  ParTech describes a medicine pill as an example of encapsulation: “All the medicine(objects) are stored inside the pill (class) and you can consume it whenever needed.” In other words, a pill and its contents are analogous to a class and its data members respectively. While ParTech is not wrong for using a pill as an example of encapsulation, I believe they explained it as a comparison rather than an example. A pill is an effective example because it has qualities (data) and operations humans can perform on it. Its qualities include a name, expiration date, and composition. Its operations include purchasing, disposing, and consuming.

Polymorphism is the state of having many forms. ParTech uses method overloading and overriding as examples of polymorphism. While method overloading and overriding are effective examples of polymorphism, they are not real-world examples. A real-world example of polymorphism is a person because a person can be a student, husband, and chef at once.

Inheritance is the practice of giving the data members of one class to another class. ParTech does not provide an example of inheritance. To understand inheritance, one needs to recognize that many objects are of the same classification. For example, a student, husband, and chef are people. The student, husband, and chef have the characteristics of people plus other distinct characteristics. If we were to implement my example in code, inheritance is the feature that will allow us to give the people characteristics to the student, husband, and chef without rewriting the code for it.

With a stronger recognition of how the object-oriented principles apply in real life, I can better translate them into software during my course and career.


Article: https://www.partech.nl/en/publications/2020/10/basic-principles-of-object-oriented-programming#

From the blog CS@WORCESTER – Andy Truong's Blog by atruong1 and used with permission of the author. All other rights reserved by the author.

The CS Series | Introduction

Welcome to my blog! For the next few months, I am going to be featuring computer science content. Stay tuned for upcoming content!

Andy Truong

From the blog CS@WORCESTER by atruong1 and used with permission of the author. All other rights reserved by the author.