Week 6

The blog I decided to read this week is UML Diagram Types. As we learn more about UML, it is important to know about the many types of UML diagrams. There are two main types of UML diagrams, Structure and Behavioral. Structure types include Class, Component, Deployment, Object, Package, Profile, and Composite Structure Diagram, while Behavioral types include Use Case, Activity, State Machine, Sequence, Communication, Interaction, Overview, and Timing. The main difference between Structure and Behavioral diagrams is Structure shows what is in a modeled system, while Behavioral shows the behavior, or what is supposed to happen in the system.

Of these diagrams, we have worked with the Class diagram. These diagrams are used primarily for Object-Oriented situations. This is because they show the classes along with their attributes and operations of each class. Component is another type of UML diagram. These, as the name implies, show the structural relationship of components in a particular system. Deployment diagrams are used to show the hardware of a system and the software used with that hardware. These diagrams are useful when you have software deployed across multiple machines. Object diagrams are very similar to Class diagrams, however Object diagrams use real world examples. Package diagrams are used to show dependencies between different packages in a particular system. Profile diagrams are relatively new to UML, and are used to profile things like stereotypes, definitions, and constraints. Lastly for Structure diagrams are Composite Structure diagrams. These are used to show the internal structure of a particular class.

For Behavioral diagrams, we start first with the Use Case diagram, which is used to show an overview of various actors that are involved in a system, how different functions are needed by those actors, and how the different functions interact. Activity diagrams are used to represent workflow, for example business or operational workflow. State Machine diagrams are similar to Activity diagrams, and are used to describe the different behaviors of objects and how they act based on what state they are in. Sequence diagrams show how objects interact with each other and, as the name Sequence implies, what order they interact. Communication diagrams are what the old UML 1 Collaboration diagram was. These are similar to Sequence diagrams, but are focused on the messages based between objects, instead of the order they interact. Interaction Overview diagrams are essentially multiple Sequence diagrams all inside another diagram, to show how many things interact and how they interact with each other, and in the order that they interact. Timing diagrams are also like Sequence diagrams but show the behavior of objects within a specific timeframe. 

I chose the following blog post because it gave clear and concise definitions and explanations of the many types of UML diagrams, and allowed me to appreciate them even more than I did before.

Link

From the blog CS@Worcester – Erockwood Blog by erockwood and used with permission of the author. All other rights reserved by the author.

Blog post 1 – UML Class Diagrams

For my first blog, I wanted to discuss UML Class Diagrams, a topic we covered in class. They help put programs in perspective by showing their structure. UML class diagrams have a very simple set up. Each class is represented by a box, and in each box, there are 3. All classes have these boxes, and all these boxes are divided in the same exact way. They look like this:

When writing class names, they must be in bold, and they must start with a capital letter. The font is also used to show other details like what kind of class it is. If it is in bold then it is a concrete class, if it is in bold and italics then it is an abstract class. If you want to denote a specific type of abstract class, like an interface, then it will use the same markdown setup as an abstract class, however, it will have the classifier «interface» on top of the class name. So, it should look like this:

Attributes are listed in a specific way, and this is something that I had a tough time getting used to. Generally, in programming languages we write the data type followed by the variable name, however in UML Class Diagrams, it’s the other way around. Attributes are listed first by name then by data type, and the two are separated by a colon. There is one more thing to touch on, and that is the visibility of the attribute. To denote a public attribute, there should be a (+) sign in front of it. To denote a private attribute, there should be a minus (-) sign in front. Finally static operations are distinguished by an underline font.

Finally, we get to operations. They work similar to attributes; the only difference is that operations are denoted with parentheses. The return type of the operation, its visibility, and so on works the same way as attributes. If a class a has a parameter, then it listed as an attribute but inside the parentheses. It should look something like this:

Note that the class name in this example should have been bolded.

Finally, we get to the last element that I will discuss, and that is relationships. Since these diagrams are meant to be a blueprint to show how programs are structured, we need to show how the classes interact with each other. Tis done with arrows. There are three different types of arrows that show different types of relations.

Solid Arrow: The class utilizes the attributes of the class it points to.

Hollow Arrow: The class extends the class it points to.

Dotted Arrow: The class implements the class it points to.

This is how they look like in use:

This is a very basic overview explaining my understanding of how UML Class Diagrams work. There are many other elements that left out such as multiplicities and composition. I recommend using the sourced I used for further reading:

https://www.uml-diagrams.org/interface.html

https://www.uml-diagrams.org/class-diagrams-overview.html

https://www.guru99.com/uml-class-diagram.html

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

Strategy Pattern Design Article

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

This article shows the “intent” of the strategy design pattern and how to successfully use it when refactoring code which is our current class topic. According to the article the strategy pattern (a behavioral design pattern in CS helps define a group of algorithms in separate classes which will effectively use each other’s objects.

One of the larger issues addressed by using the strategy pattern helps keep the main class from growing into a more complex mess. The strategy pattern allows for a developer to take/extract a class that has different functions and funnel them into a new class which is what this pattern refers to as a strategy.

Interfaces are commonly used with the strategy pattern in order to communicate with the other “strategies” that you previously extracted from the main class. The use of interfaces in the strategy pattern also allows your code to switch between algorithms at run time by using sub objects that perform their own tasks.

I chose this article as I feel it gives readers like myself a good general understanding of how to use and implement the strategy pattern. The article effectively shows you when you should or should not use the strategy pattern along with the pros and cons of using it. Similarities between the strategy pattern and other patterns it also outlined in the article which helps you tell the patterns apart and when you should use one pattern over another.

This article from refactoring guru has helped me to better understand the strategy pattern as a whole and helped me gain a somewhat smaller but still important understanding of some aspects of other design patterns (for example command and state). There are also examples of the strategy pattern being used in different coding languages found under the “Relations with Other Patterns” section.  I plan to use the information in this article to help me understand the Strategy pattern more in current and future assignments as well as in my professional career whenever I may need to refactor code through the different design patterns.

Overall I believe the general understanding of the strategy pattern gained from this article can help myself and any other student that may be having trouble with the topic or even someone who is just curious and would like to learn more about design patterns as their are articles on the other design patterns on the same website that can be accessed easily through links near the end of the page.

From the blog CS@Worcester – Dylan Brown Computer Science by dylanbrowncs and used with permission of the author. All other rights reserved by the author.

Software Construction Log #2 – Learning about Containerization and Virtualization

            In my experience, the concept of virtualization is currently synonymous with the creation of virtual machines that are used to emulate hardware and operating systems that, for one reason or another, are not readily available during the process of software development. For example, during my studies I have needed to use programs that were not available on Windows operating systems or to study an operating system for which a physical unit may not be readily available. Whatever the case may be, virtualization is not a new concept, and it is widely utilized in software development. It is important to note that virtualization is not exclusive to virtual machines, as it has a broader range that includes any concept related to the abstraction of a system’s physical components into virtual components.

            Among others, one concept of virtualization is containerization, with which most of us are familiar through Docker. Conversely, containerization refers to the containment of applications, their dependencies, and their required operating system into a singular package, also called container (hence, the name) that can be deployed and used on any operating system. By design, containers are meant to be a portable and lightweight way of testing and deploying applications, at least when compared to virtual machines. However, it is important to note that singular instances of containers cannot be modified, whereas it is possible to customize and modify virtual machines. Despite the caveats or benefits of virtual machines and containers, both are equally important during development.

          As I mentioned before, I have used virtual machines during my studies to create and use servers that I had no immediate physical access to, so the concept of virtual machines is not entirely foreign to me. However, I have little experience by comparison when it comes to Docker and using containers for software development, so I believe it is important for me to understand their differences so that I can know how to properly utilize them. As I was researching more regarding the concepts of virtualization and containerization, I came across the post titled What’s the Diff: VMs vs Containers on BackBlaze.Com, in which Roderick Bauer defines what virtual machines and containers are in detail, how they are different based on their structure on a server, as well as listing their benefits and best uses. Though Bauer does not directly state their caveats, by looking at the differences of both virtualization and containerization I can better understand when either approach could be more suitable depending on the needs during development.

            Moreover, what this post also helped me understand better is that neither option is mutually exclusive; it is possible (and sometimes, even preferable) to utilize both virtualization and containerization during development, rather than being limited to either option, so long as doing so does contribute to improving development.

Direct link to the resource referenced in the post: https://www.backblaze.com/blog/vm-vs-containers/

Recommended materials/resources reviewed related to virtualization, virtual machines, and Docker/containerization:
1) https://www.oracle.com/cloud-native/container-registry/what-is-docker/
2) https://www.infoworld.com/article/3204171/what-is-docker-the-spark-for-the-container-revolution.html
3) https://www.docker.com/resources/what-container
4) https://devopscon.io/blog/docker/docker-vs-virtual-machine-where-are-the-differences/
5) https://www.airpair.com/docker/posts/8-proven-real-world-ways-to-use-docker
6) https://opensource.com/resources/virtualization
7) https://en.wikipedia.org/wiki/Virtualization (Definition of Virtualization)
8) https://www.ibm.com/cloud/learn/containerization

From the blog CS@Worcester – CompSci Log by sohoda and used with permission of the author. All other rights reserved by the author.

Junit and Temporary Files

               When working with a Java program, one of the strongest tools to ensure it is functioning is Junit testing. Junit testing makes it easy to take a glance and see if all properties of your code are functioning correctly. Despite this however, at the end of the day, the product must be able to seamlessly accept and output data in a usable form. Therefore it is important to understand how to use temporary test files when using Junit.

              Andrew Binstock’s post fits in with regards to the currently assigned homework which sees us utilizing test classes and modifying them as the code is refactored. These tests allow us to ensure that the written code is working properly. To build upon this idea the post linked below presents the idea of Junit testing with temporary files to read and write to. Within this post is sample code which creates temporary files in and out of Junit testing.

Below we can see a snippet of code from the original blog post which shows temporary files being used in a Junit test. (Andrew Binstock)

import org.junit.jupiter.api.*;
import org.junit.jupiter.api.io.TempDir;

import java.io.*;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;

import static org.junit.jupiter.api.Assertions.*;

public class TempFilesJUnit5Test {

Path path1, path2;
File file1, file2;

/* This directory and the files created in it will be deleted after
* tests are run, even in the event of failures or exceptions.
*/
@TempDir
Path tempDir;

/* executed before every test: create two temporary files */
@BeforeEach
public void setUp() {
try {
path1 = tempDir.resolve( “testfile1.txt” );
path2 = tempDir.resolve( “testfile2.txt” );
}
catch( InvalidPathException ipe ) {
System.err.println(
“error creating temporary test file in ” +
this.getClass().getSimpleName() );
}

file1 = path1.toFile();
file2 = path2.toFile();
}

               Within the second homework assignment we can see that Junit tests are used to ensure that the different classes of ducks and working properly and that the data output is correct. Some of the Junit tests scan the output file and compares it against the expected output. While this is useful to ensure the code works, it is also important to consider that not everyone will want their output confined to the terminal. This program could very easily be modified to output to a text file for data collection purposes. Testing this with Junit would allow the creator to ensure that data is being retained properly before running the program in a real case scenario.

Testing with temporary files was previously an underutilized method of testing due to older hardware being much slower and older drives using spinning magnetic disks rather than modern solid state storage. In the post we see the author discuss this dated policy and encourage the use of test files to create a more thorough testing method. Some might want their output in a text file or as an output to a front end for a website. Junit tests with temporary file allow you to test for this functionality as these temporary files can be created, read from, written to, and are all deleted at the end of testing to keep drive space free from clutter.

Bibliography:

Binstock, A. (n.d.). Working and unit testing with temporary files in Java. Blogs.oracle.com. Retrieved October 11, 2021, from https://blogs.oracle.com/javamagazine/post/working-and-unit-testing-with-temporary-files-in-java.

Working and unit testing with temporary files in Java (oracle.com)

From the blog CS@Worcester – George Chyoghly CS-343 by gchyoghly and used with permission of the author. All other rights reserved by the author.

Factory Method vs Abstract Factory

For this week’s assignment, exercise #2, I had an opportunity to refactor a poor design of Duck Simulator using the factory pattern. It was nice that I could approach this design pattern step by step and learned its definition by understanding why I had to create an abstract method or why I had to create a factory class. Moreover, after skimming through a long chapter, Chapter 4. Baking with OO Goodness: The Factory Pattern, although there are many important definitions in this chapter, I believe that there are two concepts that I shouldn’t miss, the factory method and the abstract factory. Both are new tools that I need to know what they are and how to apply them to a design.

Furthermore, for better understanding, I also wondered what was the difference between factory method and abstract factory. Although, the textbook has a comparison between those two concepts, but for myself, it was long and difficult to follow till the end. So, I did a few searches to see if there were any good resources that I could take a quick look at for my question. I found a good blog, called Factory Method vs Abstract Factory. In this blog, the writer makes some comparisons to show the difference between factory method and abstract factory. Through the blog and the textbook, I know that both concepts are used to encapsulate object creation, and they apply the dependency inversion principle by allowing coders to decouple code from concrete classes . On the other hand, the two concepts differ in many ways. First, the number of products produced is different. The factory method is used to create only one product while the abstract factory is used to create families of related products. Second, for the factory method, the object creation is decided by subclasses (depending on inheritance), whereas the abstract factory has a separate class to creates a family of products, then its object can be passed to client class for using (object composition). Next, it is the level of abstraction. Since the abstract factory are at higher level in abstraction, we can use factory methods to create products in factories.

For myself, this is a resource worth referring to because its concise, well-organized content helps readers easily distinguish the difference between the two concepts. Thanks to this resource, I got a better understanding of the factory pattern, especially the abstract factory and factory method, which is really helpful for my diagram design latter.

From the blog CS@Worcester – T's CSblog by tyahhhh and used with permission of the author. All other rights reserved by the author.

From Warcraft III to My PC: My Inevitable Pairing with Polymorphism

The year was 2005. I was a young child in elementary school, and eventually I was exposed to a little-known strategy game known as Warcraft III. As I championed the human race in my epic quest against the Undead Scourge of Lordaeron, I came across a sorceress ability known as “Polymorphism”. This powerful spell allowed its caster to turn an individual target into a harmless sheep. While entertaining and useful to say the least, little did I know that Polymorphism itself would take on a new form in the years to come…

Fast forward to 2021. I am being exposed once again to Polymorphism, this time as an essential feature of Object-Oriented programming. This would mark the third time that I am working with this concept (the other times being 2016-2017, and 2019 respectively). Polymorphism, in theory, isn’t very difficult: we take one idea (such as a function/method), and give it “many forms” (hence the name) among its various classes that use the function/method.

Listed below is an article about polymorphism from GeeksForGeeks, one of my “personal go-tos” when it comes to learning about programming practices. Specifically, “runtime polymorphism” will be more applicable in my software design class, due to its usage of method overriding. When using the “Strategy Design” of refactoring, we will create various interfaces and have them implemented using respective classes; these classes will then create their own version of the method.

Strategy design refactoring seems to provide an edge over “simple inheritance”, which would involve having a single base class (that all subclasses inherit off of). This “edge” is the removal of inherited methods that serve no purpose in certain subclasses; when the interface is implemented by the class, we can choose exactly what we want and don’t want from polymorphism.

However, having too many interfaces, or not enough data within the interface can cause its own problems. In addition, an interface is just that: a “top-down” view, with nothing beneath it; the methods need to be designed by the class using it. Meanwhile, inheritance may have redundant data, but at least you get all that and a bag of chips. In other words, inheritance provides one portion of functioning methods, plus whatever else is added on in the subclass.

I hope that I can use the idea of polymorphism, alongside interfaces, to reduce the amount of redundancy and complexity in my programs. There is no need to turn a program into a headache with unnecessary amounts of inheritance. In addition, part of this unnecessary material could be redundant – brought along for the ride, but not used during run-time.

Link: https://www.geeksforgeeks.org/polymorphism-in-java/

From the blog CS@Worcester – mpekim.code by Mike Morley (mpekim) and used with permission of the author. All other rights reserved by the author.

Just Another Scripting Saying

Ever since the beginning of my programming career, I have had a plethora of professors provide several sayings that were helpful to becoming a better software engineer. One particular saying was acquired only a few weeks ago, during my Software Construction course. The saying goes: “YAGNI”, or when extended beyond the acronym: “(Y)ou (A)in’t (G)onna (N)eed (I)t”.

YAGNI is a useful term when considering one particular coding smell: Needless Complexity. Novice programmers often believe that they need to somehow squish every keyword, conditional statement and data structure into one massive, impressively diverse program. Yes, it is definitely useful to be knowledgeable in all of these areas. However, an advanced understanding of programming requires that one not only knows the skills, but also when to use them.

The article listed below (created by legendary software engineer Martin Fowler) explains the various reasons why YAGNI is so important. Specifically, it explains different kinds of “costs” related with unnecessary complexity: Costs of building, repairing, delaying and carrying the software. Considering these costs is such a crucial factor due to the fact that software should be designed to be cheap for the producer, yet effective and “easy-to-use” for the customer.

Understanding YAGNI, and its effectiveness against needless complexity, is invaluable to achieving proficiency in software design. The class does not want us to build products “per se”; rather, it already expects that we can build the block from the get-go. Instead, this class focuses on “whittling away” at the back-end block to create something more beautiful and beneficial.

If anything, based on the material that Martin Fowler has presented to us, we need to take a look at our code and ask ourselves: “is this really necessary?” Do we really need this exception case if the chances of achieving the error make the lottery look like a safe bet? Are these security features needed when a simple password check can cut the mustard? Cutting down on needless complexity is a rather easy smell to work on, since the problem is based on our ability to work harder than we really need to. Instead of remembering every last line of code, we should remember the abstract ideas, and learn how to translate/implement them.

In conclusion, I believe that “YAGNI” is an essential saying that every programmer should know by heart. In addition, I strongly believe that the sooner a junior programmer can learn this rule, the better off they’ll be in the world of software design. The best way to avoid certain coding smells (such as viscosity) and technical debt is to instill proficient programming practices that avoid these problems to begin with.

Link: https://www.martinfowler.com/bliki/Yagni.html

From the blog CS@Worcester – mpekim.code by Mike Morley (mpekim) and used with permission of the author. All other rights reserved by the author.

Singleton/Factory

Last week reading took us through one design pattern the singleton pattern and a quasi-design pattern the simple factory technique. I was very impressed by both and took some time to analyze their delivery method –how they presented their arguments. On singleton the author presented the design as a conversation in an almost Zen tone. I was attracted to his way of explaining because I believe that a lot of times when studying we let the stress get the better of us and miss many important points. The step by step really show not just how but why. A lot of times we write a lot of code because we know how but not always know why we write it a certain way, which I believe makes the knowledge untransferable –although why is not always important.

The relaxed Zen mode of explaining is also something I appreciate because I am a strong believer that sometimes, some things should be explained like you would explain a 5-year-old, and I have no shame in listening like a 5-year-old. It is easy to have many years of experience on something and forget some of the things taken for granted are very important to the beginner(me). The Zen approach also reminds me of Buddhist monks drawing complex sand diagrams only to erased them and start over again. It is hard to erase bad habits and acquiring good ones, but by creating the habit of erasing habits the learning cycle can be increased considerably. That’s all I must really say on how the authors carried their message, but the interesting thing was the message itself.

The singleton pattern at first was not impressive if anything I always had a bad view of private or protected variables or methods. I never really understood the need to hide things in code maybe because I never really had to write code of considerable size. Once I started working with the pattern it was like a little light bulb flickered on top of my head and I suddenly started seeing the coolness of obfuscation in this case just preventing object overcrowding. I really thought it was pretty cool and I think that in the way the idea was explained the structure will be in my head for quite some time, and I am a very forgetful person.

The simple factory technique was also well explained in just the right number of words. It was very clear that by consolidating actions or delegating the creation of objects helped to minimize how much one class was doing. Uncle bob always say doing too many things is bad, so I think this applies in this case. I was afraid at first that to implement this was to substitute the singleton pattern that I’ve gotten so fond of, but that was not the case. After implementing it I saw that there were other areas that could be greatly improved by consolidating further. My only fear is to know when to stop –how much is too much consolidation.

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

Why Encapsulation Matters

Summary:

In this article, they don’t show us examples of encapsulation but instead explain to us the importance of it and why we do it as software engineers. Initially, they start off with how encapsulation helps us hide the complexity of our code. The beauty of hiding our code is not having to understand all the details in order to be able to use it, we just need to understand a broader abstract concept and how it works and how we interact with it. They also explain to us what happens when are not able to achieve the proper levels of encapsulation in our design. That article continues as to why we need accessor and mutator methods in Java.

Reason:

The reason why I chose this article was because in class we have done a lot coding in regards to encapsulation and I thought that this would help me fully grasp the purpose and meaning of encapsulation. Encapsulation is the very essence of API’s and how they work and being able to understand this is very important since we may be creating API’s in the future.

What I’ve Learned:

Encapsulation is more than just defining accessor and mutator methods for a class. It is a broader concept of programming, not necessarily object-oriented programming, that consists in minimizing the interdependence between modules and it’s typically implemented through information hiding. Our software designs the visible parts of our modules/classes constitute their public interface, and this is exposed to the outside world, the rest of it should be hidden to the naked eye. With encapsulation us as humans deal with complexity by defining abstractions with public interfaces so that we are able to interact with them and all of the code that lies beneath it is unnecessary in order for use it. It is like an iceberg, only a small portion of it is visible on the surface, but most of its true size is hidden underwater where we cannot see it. Changes can we made in directional systems because internal implementation is encapsulated and because of that, changes can we safely done without affecting it’ public interface. By minimizing the impact of changes and independence of modules, we can achieve proper levels of encapsulation in our software that can handle change without breaking its users. Information hiding is important because it decouples modules that compromise a system and it allows for them to be tested, optimized, used, understood, and modified in isolation. This allows for other modules to be developed in parallel and eases the burden of maintenance without the fear of affecting other modules. Encapsulation is a desirable attribute that allows for the evolution of APIs and as long as we respect public interfaces of our abstractions, we are free to change whatever has been encapsulated. Failing to define proper abstraction with proper levels of encapsulation will end up causing difficulties when change happens. There is no way to change the public interface of an abstraction without breaking its users. Encapsulation is one of the tools we use that help us create good abstractions, but no level of encapsulation is going to make bad abstraction work.

Source: https://dzone.com/articles/why-encapsulation-matters

From the blog CS@Worcester – Life as a CS Student by Dylan Nguyen and used with permission of the author. All other rights reserved by the author.