Author Archives: Mr. Lancer 987

On the subject of using Simple Factories…

This week, I am going to discuss the function and design of a Simple Factory pattern in Object Oriented Programming. At a very high level, this allows a programmer to centralize and encapsulate instance creation functionality into one class, as opposed to having many different classes (or your main class) depend on a large number of different classes. In my opinion, this is particularly useful when designing code that uses the strategy design pattern, as there will be objects for every concrete strategy, and many dependencies will be created. It is much easier (in at least those instances) to encapsulate all of those dependencies and creations into one class, a factory, and have that factory be dependent on all of the classes instead.

These principles are highlighted well in this blog, which provides a use case to demonstrate the usefulness of a factory. In this post, the example used is an implementation of a creature factory (admittedly less cool than a duck factory). Before implementing a simple factory, the main class is responsible to create and instantiate different creatures, and they can be created from anywhere in the code. This works, but is poorly designed, as we have discussed in class. Any time you want to make a change to the way a creature functions, for example, you might have to go edit the code in a ton of different places, and your UML diagram might just look atrocious. To address these design flaws, we can introduce the Simple Factory pattern, which centralizes creature creation logic into one dedicated class. This factory handles the instantiation of various creature types, simplifying our main class instead of scattering creation logic throughout the code. Whenever we need a creature, we call a method on the factory, which returns an instance of the requested object.

The blog example creates a CreatureFactory class with a method create(CreatureType type), which accepts the desired creature type. Inside this method, we use a conditional statement to return the appropriate creature object based on the input. For example, if we get WEREWOLF we instantiate a Werewolf object. If we want to add a new creature type, like Phoenix, we just create a new class for it and update the factory method. There’s no need to search through the entire codebase for instances where creatures are instantiated.

I admittedly don’t do a lot of object oriented programming, but the principle of using a factory makes perfect sense to me, and is something that I do and will continue to do going forward. Centralization of creation looks clean, performs clean, and makes sense. I didn’t really get into this, but it also may be extremely useful for OOP languages that do not have automatic memory management like Java does. You could also centralize the destruction of objects, possibly allowing for efficient tracking and memory allocation/deallocation.

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

On the subject of Licensing your Code…

This week, I am going to discuss the importance of licensing your code – something that I did not know was important until this week. The blog post I will be referencing can be found here. I chose it because it provides both a simple explanation of the importance of licensing and it explicitly describes the fallacy that causes most developers (myself included) to not license their code. The blog also references some of the same specific licenses we discussed in class, which (along with some research) indicated to me that there is a small set of very popular licenses that can serve a variety of purposes and target a variety of different intents and audiences.

After reading this blog post, reading others, looking at different open source projects on GitHub, and having discussions in class, the conclusion I’ve come to is this: the top reason people don’t license their code is because they don’t understand that licensing actually gives people more rights, not less. Many (again, my prior self included) likely think that if you just code something and throw it onto GitHub, that anybody can use it as open-source. This is not the case; that is actually incredibly restrictive, because you own the copyright to that work, and nobody can use that code without running into some legal barriers. Whether those barriers will ever be realized is another question, but not including a license may be enough to deter people from expanding on your work. A well-chosen license clearly communicates how others can use, modify, and distribute your work. This not only protects the rights of the original creator, but also allows others to expand on the work without the constant worry of stepping on legal toes. Licensing is better thought of as a way to invite others to engage with your code, rather than a barrier that restricts access.

The MIT License, to give an example, is concise and straightforward, allowing users to do almost anything with the code, as long as they include the original license and copyright notice. This simplicity has made it a favorite in the open-source community, encouraging collaboration and making it easier for developers to share their projects without too many legal constraints.

Understanding code licensing not only protects your work but also leads to a more collaborative and innovative development environment. Whether you want to encourage broad usage with an MIT license or ensure that your project remains open-source with a GPL, the right license can significantly impact how your code is shared and utilized. Moving forward, I plan to include licenses in any open source code I write. Though I never thought it was important before, I’ve learned now that it actually is critical if I want my code to actually be usable by others.

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

On the subject of Inheritance…

In this post, I will be exploring the concept of inheritance in object-oriented programming. Inheritance is one of the core principles of OOP that allows a new class to inherit properties and behaviors from an existing class. The largest benefit of inheritance, in my opinion, is the ability to eliminate unnecessary (or otherwise necessary) repetition in the code. This week, we discussed design smells, and excessive repetition is one that can make code incredibly tedious to read and maintain, and it is one that can be eliminated or minimized by proper use of inheritance. The blog post I will be referencing this week can be found here, and it provides a very detailed example of inheritance as well as some further explanation of vocabulary and more advanced concepts that we have not yet covered in class, like upcasting and downcasting. I chose it because of these extra details it provides; most resources I found about inheritance provide the definition and a basic example, without going much further.

Let’s consider a practical example related to the one used in the blog post. Imagine you’re developing a software application for a zoo. You might have a base class called Animal that includes properties like name, age, and methods such as makeSound(). From this Animal class, you could create specific subclasses like Lion and Elephant. Each of these subclasses would inherit the properties and methods from Animal, allowing you to easily manage common functionality while still being able to define unique behaviors for each animal.

To expand on some of the details provided in the blog post, we could also create an instance mufasa of the Lion class and assign it to some Animal a1 = mufasa;. This would be allowed as upcasting, since Lion extends Animal. We could also then downcast a1 back into an instance of the Lion class, because at runtime, a1 will actually be a Lion instance.

Again, the main advantage of inheritance is its ability to promote code reuse. Instead of duplicating code across multiple classes, you can simply extend an existing class. For instance, if you needed each animal to have a method eat() that does the same thing for any animal, you could just implement it to the Animal class instead, saving time and space and keeping your code cleaner. The elegance of inheritance lies in its ability to create a hierarchy of classes. In our zoo example, you could further extend the Elephant class to create subclasses for different species of elephant, each with its own unique features, all while retaining the common behaviors defined in Elephant. The real world is full of hierarchies, and understanding how we can mirror those relationships programmatically when we want to represent or implement them in our code is a critical skill to have for an object oriented programmer.

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

On the subject of Output-Oriented Software Design…

This week, I am going to discuss some of the benefits of the output-oriented software development methodologies we have been studying in class, like Scrum and Agile. I have built many projects both on my own and for my career from the ground up, which is where the value of these methodologies is most apparent to me. The blog post I will be referencing throughout this discussion can be found here. This post provides an in-depth overview of the Agile methodology, including lower-level analysis of different stages of the process, benefits and purposes of each stage, and various best practices for different stages. I chose this post because it correctly emphasizes the importance the Agile methodology places on continuous delivery, which is something that has been a cornerstone for me in various projects.

A project that comes to mind is actually the same project I discussed in this week’s post for CS-343. A friend came to me and asked for something way above my skill level, and it was daunting to imagine planning out the whole project and implementing/deploying some large framework in any reasonable amount of time. If I hadn’t remembered something an old professional connection had said to me years prior, I don’t think I ever could have known where to start: “your code has to exist before it can be made better.” I think that is what the heart of these continuous delivery methodologies is really about, and it really is a true statement for many reasons. The first, which this blog touches on and which we have discussed briefly in class, is that your perspective will always be better or wider after the work is started. Another reason that statement holds true, and perhaps the most practical reason (at least in my case), is that half the time, I don’t even know what I am doing when I start. It would be impossible for me to design anything, because I don’t know anything. For me, learning my way through a project is almost all the fun, and that is not really an option without methodologies like Scrum and Agile, even if I don’t know I’m using them. This blog post discusses release management a lot, which is not so applicable to personal projects, but I think it connects nicely if you compare a release to a checkpoint or successful implementation of a new feature. In my project, as I built it, I started with: what. Then, I said, I guess I could try that. Then, I implemented a single shoddy feature. I saw my feature and saw a way to make it better. Compound that a hundred times, and I had a full framework that I had approached incrementally, following Agile principles and release management without even knowing it. I think that is a testament to the elegance of these continuous delivery oriented methodologies, and I will more consciously follow these principles moving forward.

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

On the subject of Abstraction…

In this post, I will be discussing some basic concepts about abstraction in object-oriented programming. The resource I reference can be found here. I chose this topic because in the first few group activities, I was made aware that I had forgotten some of the key differences between kinds of abstraction (at least in Java), such as the difference between an abstract class and an interface. Though we reviewed these differences in class, I wanted to continue to find specific examples that would allow me to better understand the concept. Abu’s blog post briefly explains what abstraction in object-oriented programming is, some of its benefits/purposes, and some elementary examples of how to implement (no pun intended) abstract classes and interfaces.

The largest point of note I want to discuss is the benefit of modularity when abstraction is implemented. I recently finished up a personal coding project, in which modular development was a necessity. The project involved a central framework capable of ingesting a very specific kind of data from different websites, but each of the websites had a different way of providing that data. The most efficient answer I could think of was to make the central framework independent of the websites themselves, and to make it deal only with the data after it was obtained. I then created a module for each website that held the data, and implemented whatever logic I needed to in order to get the data and pass it to the central framework. I used Python for this project, but in hindsight, I may have been better suited to implement an object-oriented programming language like Java. Each module could have been a concrete class that extends some abstract class Parser, as each of my parser modules in my Python project used the same methods anyways. Each module had a get_url_and_interactions() function, a get_parse_function() function, and an stm() function (we can leave that abstract for now). It would have been very simple to use an object-oriented programming language, as I could have abstracted what it means to be a parser.

Now, this worked fine; since I was the only developer on the project, and had full visibility over all of the code, I didn’t need to check if a module implemented, for example, the get_url_and_interactions() function. I knew that it did. Moving forward, if I were coding more collaboratively with anyone else, or even if I just wanted to code according to some better practices moving forward, I could have used abstraction to standardize the parsers to ensure they all implemented certain methods or functions.

Though a little cliche, I do think it is very nice and elegant that the same thing can be accomplished in so many different ways. I think it is a good metaphor for most problems worth solving.

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

CS 348 Introduction Post

Hey. I am a student at WSU taking CS 348. This is a test post to introduce the blog and make sure it appears on the CS@Worcester blog.

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

CS 343 Introduction Post

Hey. I am a student at WSU taking CS 343. This is a test post to introduce the blog and make sure it appears on the CS@Worcester blog.

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