Category Archives: Week 3

Understanding Continuous Integration and Continuous Delivery (CI/CD)

While good testing and version control habits are always helpful and save a lot of time, the process of committing changes, running tests, and deploying the changes can in itself be time consuming. This is especially true in an agile development process, which aims to make small, incremental changes in a series of sprints. Ideally, the process of committing, testing and delivering could be done in a single command.

This is where CI/CD comes in. An Oracle blog post on CI/CD describes the software development pipeline as being a four-step process: commit, build, automated tests, and deploy. CI/CD involves automating this process so that a single commit results in changes deployed to production, so long as the changes can be built and pass the tests. However, any of these stages can be skipped and not all of them have to be automated if it doesn’t make sense to do so. Additionally, other stages can be added if desired.

Oracle stresses the importance of testing in this process, and the requirement to have a suite of unit, integration, and systems tests. These are important to have for any project, but are vital if a commit is automatically deployed to production to make sure users are getting a reliable product.

Gitlab uses Runners to run the jobs defined in a file named “.gitlab-ci.yml”. Jobs can be defined in the stages mentioned above, or any arbitrary number of custom stages, to create a single pipeline. When a commit is made, the pipeline lists the stages and whether they pass. Of course, unit tests should be run before a commit to ensure that the code is behaving as expected, but once a change is committed the rest of pipeline can be automatic.

In large systems, this automation is especially useful. You may be not able to compile an entire code base on a local machine. You may not be working on the same schedule as the rest of your team. Automating other portions of testing and deployment allows a single developer to finish a feature or patch on their own and reliably get it into the hands of users.

In researching software engineering jobs, it seems that many companies use Docker as part of their CI/CD process. Imagine you want to make sure your software runs on Mac and Windows machines. Docker can use predefined images to build isolated containers in which the code can be run. A pipeline can contain separate build stages, for example, to make sure the code builds on both operating systems before running tests and deploying. Next week, I will look at Docker in more detail and describe how it can be applied to software testing.

From the blog CS@Worcester – Inquiries and Queries by ausausdauer and used with permission of the author. All other rights reserved by the author.

The Importance of Writing Well

Today I stumbled upon a blog post titled: Undervalued Software Engineering Skills: Writing Well by Gergely Orosz. That can be found here: https://blog.pragmaticengineer.com/on-writing-well/. I found this linked tangentially where the author was mentioning that in order to create clear diagrams that everyone can follow, honing your writing skills in general is one aspect of accomplishing that.

In this blog post, the author talks about how writing and communicating is a very under-appreciated skill that a software developer can have. I think that software devs have this stigma that they are not great communicators and maybe not particularly good with words, so this may be a surprise to some. However, writing well is the first step in creating diagrams that can be followed and amended by a team that is working on a project.

As someone that has worked in the corporate world for a long time with massive amounts of cross-communication between different departments, I can tell you that writing is something that people in every profession could stand to do better. Sometimes something as simple as communicating your thoughts precisely, concisely, and interestingly can be enough to get you noticed, even in a large corporate environment.

The author mentions that for a software dev, writing can be a tool to “influence engineers and other teams outside of your immediate peers.” He also frequently mentions durability, and how the better you are at writing, the more “durable” your decisions, trade-offs, and ideas will be. This will not only help your own career, but will help your team manager their project better.

I am pretty passionate about writing, and I think that in any career, having a grasp on good writing practices can make a huge difference for how you are perceived by your peers, and for a skill that is often seen as ancillary, can be a real game-changer.

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

SSSSSolid says the snake

SOLID is an acronym for a set of important design principles. Paired together they create a framework for worry free code, and by “worry free” I am speaking of code that would trouble you if any changes needed to be made. In the world today things are constantly changing and being updated and so should your code. If that’s the case then any code you write should have the ability to be edited without causing a complete overhaul of your whole program. Basically what you want to avoid is trickle down effects, and unlike trickle down economics, this is real. If you change one thing or responsibility of a class or variable and that causes a cascade of continuous changes and troubles, then you are experiencing this trickle down effect. To help with this issue is the first design principle in the acronym, Single Responsibility Principle.

Single Responsibility Principle is exactly what it sounds like. Give your classes and methods a sole responsibility so that if they are changed it will only effect that method or classes responsibility. If a class or method handles multiple responsibilities then changing the design of one part may be cause to change the entire entity. 

A crude example would be a Rectangle Class. Let us say you have a constructor to build a rectangle object and all it does is take arguments for height and width. However, you also add if and else statements in the constructor to see if the dimensions make a square and printing a confirmation message if it is. Perhaps you even write “if (myShape.isSquare())..” to send the object to a method to, but this is giving the constructor more than one responsibility. If you decide to change the placement of the square check then there will either be duplicated code or you will have to edit the constructor to pass the isSquare result to other methods. Doing any of this would result is test case changes if you were testing the code. In this scenario it is best to have the constructor just be the constructor and to dedicate the square check to its own method like isSquare. In this case if changes were made then only a single class would require changes and not several that are connected in a convoluted fashion.

I think the Single Responsibility Principle is a must know. I remember beginning coding is CS140 and Data Structures and I would try to get as much done in as few methods as possible by cramming in multiple functions into them. I thought the less methods the better but I was so wrong, it’s worth so much more to have many separate methods and classes that each have a sole function. This way code is organized, easy to arrange, and simple to implement or change.

SOLID Design Principles Explained: The Single Responsibility Principle. (2018, December 17). Retrieved from https://stackify.com/solid-design-principles/

From the blog cs@worcester – Zac's Blog by zloureiro and used with permission of the author. All other rights reserved by the author.

Digital Code apparently can smell.

How can code smell? This was my
question last class in my Software Architecture class, and I was surprised to
learn that it can. Not literally of course, but because code can be written in
a manner that somebody may say that there is something going bad in here, as
food would. According to Wikipedia
Code Smell is
: “any characteristic in the source code of a program that
possibly indicates a deeper problem” and “Code smells are usually not bugs;
they are not technically incorrect and do not prevent the program from
functioning. Instead, they indicate weaknesses in design that may slow down
development or increase the risk of bugs or failures in the future.” This is a
very interesting topic in my opinion because it can make me and other alike to
be a better coder and help us avoid common mistakes.

While searching for some more
information about the topic I have stumbled upon blog by Jeff Atwood that gives
and describes different kinds of smells that code can have. This directly related
to my class and helped me to specify different problems that can arise when I create
some software. In the class we have described smell in a little bit broader
scope then in the blog, which describes more detailed cases. For example,
Atwood gives us this: “Long Method – All other things being equal, a shorter
method is easier to read, easier to understand, and easier to troubleshoot.
Refactor long methods into smaller methods if you can.”, and in my opinion
anyone writing code nowadays can agree with that assessment. I know it can be
hard sometimes to write a short method because it would be more functional, and
that is a one of the subjects of one of my classes I took before about writing
clean code.

In my opinion this blog is a great reference
for everybody who wants to keep in mind problems that can arise, or to say avoid
you code from smelling a certain way. I know it will be helping me a lot both
in my school and professional life. Eventually anybody can learn this by heart
and know it  at the drop of a hat, but
for me until it will become almost a reflex I know I will be probably using
this post and other like it as a reference. Anybody who has plans to have a career
in a Computer Science field should learn this.

From the blog #CS@Worcester – Pawel’s CS Experience by Pawel Stypulkowski and used with permission of the author. All other rights reserved by the author.

Refactoring: Spring Cleaning for Code

Depending upon the subject, some of us are lucky to finish a functioning project so the thought of improving code after the fact – especially if there’s a new project due soon – is a distant one. However, they may be tricked into refactoring their code if asked when you say the magic words: “Refactoring is not rewriting code”. The definition, as defined by its creator is:


“a change [or changes] made to the
internal structure of software to make it easier to understand and cheaper to
modify without changing observable behavior.”


In
reality, the process may involve:

  • new
    code, but it must not change the behavior of the original code;
  • ensuring
    the system works before and after each refactor, including original unit tests;
  • creating
    unit tests to verify our refactoring has not changed system behavior;
  • changes
    that individually are minute, but combined lead to a healthier program;
  • eliminating
    duplicate code, potentially changing variable names, and more.

It is not
simply cleaning up code, but rather reorganizing it in order to make it easier
to trace and understand, as well as add functionality to in the future.

              For our purposes, this may be a very
important concept to learn but it may be some time before we get to implement
it, unless we’re coding or maintaining an entire program for our capstone; however,
it is important to understand when to do so. According to my sources, the best
time to do so is before you add new features to an existing program, or right
after you’ve already shipped it. For the former, it makes these new features much
easier to add when the program is much more readable and makes the program better
for having made the changes. As for the latter, it makes a lot of sense to
snoop around for ways to reorganize code after you’ve spent so much time on it,
and in a mad dash to finish it towards the end no doubt. Years’ worth of work
is no doubt going to have some inconsistencies that fell through the cracks in
the course of development.

              As for implementing these changes, there are several methods, including Red-Green-Refactor, Abstraction, Simplifying Methods, as well as many others we won’t cover. In R-G-R, red means stop and determine what to develop – usually with a new test that fails, getting this new development to pass tests (green), and finally refactoring to optimize. Abstraction is used to address duplicate code and can be done by restructuring hierarchies using the Pull-Up [pulling up code into a superclass to be shared more effectively] or Push-Down [pushing down code to more subclasses from a superclass] method. Finally, Simplifying Methods is an effort to simplify older code by consolidation and reducing interclass complexity. Hopefully this helps develop an understand of refactoring, in fact, I had to do quite a lot of refactoring to this blog to get it down to size!


Sources:

Refactoring – Martin Fowler
Refactoring – Agile Alliance
Code Refactoring Best Practices: When (and When Not) to Do It

From the blog CS@Worcester – Press Here for Worms by wurmpress and used with permission of the author. All other rights reserved by the author.

The Factory Design Pattern

There are many design patterns that assist in building software architecture. They fall into four categories: creational; structural; behavioral; and concurrency. Each of these groups has many specific design patterns, but to focus on more than a single pattern in a blog post would be remiss.

The Coding Blocks Podcast has a series on design patterns, the first of which discusses creational patterns, which are described in the “Gang of Four” book, “Design Patterns” [1]. While the hosts find the overuse of these design patterns humorous, they admit that seeing the word “Factory” instantly describes code at a higher level. Furthermore, design patterns assist in adhering to other object-oriented design principles.

[Design Patterns] help make a system independent of how its objects are created, composed, and represented. 

– Design Patterns, Gamma, E., et al

I have come to strongly dislike nested if statements, checking if a subclass is an instance of a superclass, and switch statements. Clean Code by Robert Martin [2] has influenced that a lot, because it made me realize there’s a better way.

Imagine an app that asks the user what kind of Car they would like. This car needs to drive(), brake(), and calculateFuelCost(). Assume there are dozens of types of Car, each implementing the Car interface with these methods. The app will need a bloated switch statement to make all of these concrete classes, depending on user input.

The idea behind the Factory design pattern is that there is a separate class that creates concrete objects, but returns an abstraction (an abstract class or interface). You don’t need to scatter logic across an application that determines which type of “Car” should be created, for example. In fact, you don’t even need or want to know what kind of car it is, once it’s created. A CarFactory class returns an Abstract Car or a Car Interface. In the case of an interface, concrete classes such as ElectricCar or HybridCar implement the Car interface.

The result is an application that can create a CarFactory, tell it what kind of car the user wants, and then manipulate the returned interface as needed. And no matter the concrete object it gets back, it can be treated the same. This separates the application logic from specific implementation of concrete Car classes.

So when your application needs to add a FlyingCar option, a concrete class can be created that implements the same Car interface. The application only needs to tell the CarFactory to create a new FlyingCar object. The rest can be treated identically, because the CarFactory returns an interface with all the required methods.

As stated in the podcast episode, if this is confusing it means you’re learning. These patterns are not trivial to learn, and require many more examples and plenty of UML diagrams to fully understand the idea behind the pattern.

[1] Gamma, E., et al. Design Patterns:Elements of Reusable Object-Oriented Software. Addison-Wesley, 1995.
[2] Martin, Robert C., et al. Clean Code: a Handbook of Agile Software Craftsmanship. Prentice Hall, 2016.

From the blog CS@Worcester – Inquiries and Queries by ausausdauer and used with permission of the author. All other rights reserved by the author.

Thinkin ‘bout KISS‘n you


KISS
(Keep it Simple, Stupid) is potentially one of the most culturally pervasive concepts
used in Computer Science, the other being maybe blockchain – the difference of
course is that people actually understand what KISS is, everyone who says they
understand blockchain is lying. Of course, KISS did not originate in Computer
Science, and instead was popularized at Lockheed Skunk Works by noted
tangential war criminal and engineer Kelly Johnson. While it may be difficult and
seemingly sacrilegious to try to explain something so self-explanatory that is
what I hope to do, flying in the face of the concept of simplicity to stretch
four words into four hundred.

Credit: csiaexchange

              It begins with, put kindly, making
distinctions about the semantics of the scant few words in this phrase; put
more bluntly, being pedantic. This examination is important, and the linked
article does a great job of highlighting first the distinctions between ‘simple’
and ‘easy’, which could be mistaken as synonyms, and contrasts it with ‘complex’.
His conclusion is this, a simple system is defined by what it is not, which is one
with too many parts which are interconnected – with the latter being worse in
software development.

              This all sounds wonderful on paper,
and about the same on a computer screen, but sometimes complexity is
inevitable. So, it is advised that you make things as simple as possible, until
you can’t, at which point you are vigilant in handling that necessary
complexity. For instance, I could try all sorts of methods to navigate a 2D
array in some mock-up code, but I don’t need to introduce recursion or anything
outrageous to shorten a method body if a simple nested loop will do.

              This idea of simplifying through pruning
code is expressed in the next sections of this post, stressing the importance
of cleaning up dead or underutilized code so that no resources are wasted maintaining
or reintegrating useless code. Additionally, YAGNI (yay more acronyms) states
more or less the same thing, encouraging programmers to implement the essentials,
that will actually be presently utilized, and skip the bells, whistles, and
maybes. Code with bunches of maybe methods require time and resources to
maintain and if they aren’t actively being utilized, then they’re a waste of
both.

              From here on, the blog introduces
many more concepts that are possible to cover in just this blog post – although
I do hope to mention Lasagna Architecture in another post sometime later. Instead,
I think it is time to bring this post to a close. What is the take-away then?
Well its exactly what you thought it was from the first line. In conclusion, it
may be appealing to get a jump on features you may want to implement in the future,
but it is best to keep things as simple as possible and/or only as complex as
needed but no more.


Sources

KISS Principle Explained
KISS, A Design Principle

From the blog CS@Worcester – Press Here for Worms by wurmpress and used with permission of the author. All other rights reserved by the author.

Anti-Pattern Cannon


“…an
atomic plant is so vast, so expensive and so complicated that people cannot
grasp it, and rather than try, they fall back on the assumption that somebody else
checked all the details before it got this far… A bike shed on the other
hand.  Anyone can build one of those over
a weekend.” –
Poul-Henning


While the blog post I have chosen
does not lead with Bike-Shedding, it is certainly one of the most interesting
examples of “Anti-Patterns” – practices in programming that are counterproductive
to both actual development as well as implementation – and provides a hilarious
anecdote, of which the quote above is from. While perhaps less entertaining, this
post outlines nine types of coding Anti-Patterns and defines what they actually
are, why they are bad, how to avoid them, and provides – my favorite –
examples, among other notes. Most importantly, these concepts are tied to code
smell, and I hope to explain the links between code smell and the practices
that cause it.

Credit: refactoring.guru

For instance, the first Anti-Pattern is Premature Optimization: As the name suggests, it is trying to code for bottlenecks you may have rather than using tried and true methods and finding the actual bottlenecks on runtime. As mentioned, in my own code I have a similar problem where I attempt to write everything perfectly, or in as few lines as possible, instead of building a working a prototype and then cleaning up code after review.

While perhaps not identical to this pattern, the tendency to get hung up on all the possibilities and edge cases just slows development and often the actual execution of the code. Code that has developed in this way is very similar to a code smell known as Speculative Generality, which is defined as excess code created “just in case”. The only difference is that instead of excess optimization code this smell is more interested with future features.

Another relevant example is the God
Class: a single class that contains and controls aspects for an excessive
amount of child classes. When code is structured in this way it makes maintenance
an obvious nightmare. This reflects two code smells most closely, Large Class
and Shotgun Surgery which are tremendously large classes that need to be split
into smaller pieces and the need to fix smaller problems spread across several
classes as a result of another change, respectively.

Credit: refactoring.guru

This trend continues with the Fear
of Adding Classes pattern reflecting the aforementioned Large Class smell;
Useless Class pattern and Lazy Class smell; and the trend continues. What I
wish to express mainly is that these two concepts exist on a continuum with Anti-Patterns
on the development end and code smell on the completed program end. So as we move
forward with the course I’ll try to be cognizant of the Anti-Patterns that lead
to poor code – as well as those which slow development cause of interpersonal
issues which I didn’t get to discuss in this particular post – and how this
poor code exhibits various code smells.


Sources:

From the blog CS@Worcester – Press Here for Worms by wurmpress and used with permission of the author. All other rights reserved by the author.

UML Diagrams

https://tallyfy.com/uml-diagram/#class-diagram

This web article focuses on UML diagrams and the many reasons why they are so handy in the world of programming. First off, the article explains at a base level of understanding about what UML diagrams are used for. They are sketches, blueprints, and a way of documenting your code before and after it is written. I chose this article because it explains the practical use of UML diagrams and includes many examples. There is so much organized information in the article that it cuts down the google searches and wild goose chase if you have any questions. Check out this organized guide to UML diagrams before you search all over.

Ceta, N. (2019, August 25). All You Need to Know About UML Diagrams: Types and 5 Examples. Retrieved from https://tallyfy.com/uml-diagram/#class-diagram

From the blog cs@worcester – Zac's Blog by zloureiro and used with permission of the author. All other rights reserved by the author.

Finishing Initial Comparisons and LibreFoodPantry Retreat

Last Wednesday night I finished my comparisons between GitLab Gold and GitHub Free. I’m happy that I managed to get through all of the features before the LibreFoodPantry retreat the following day. I found that most of the features left for GitLab Gold did not have comparable versions in GitHub. This is more of what I was originally expecting and so the remainder of the table has a lot of features marked GitLab Gold exclusives. There was also a trend with the GitLab features that most of them would relate to one overall feature such as having Epics so since GitHub doesn’t have a native Epics feature it wouldn’t have any advanced features related to managing and tracking Epics like GitLab does. I also found that some of these features were harder to compare between platforms since most of them were more advanced, enterprise grade features than the earlier ones. This is again also due to how well the documentation for both platforms explains the features and how to use them.

Thursday was the beginning of the LibreFoodPantry Retreat. We started off by going to lunch and having casual conversations before the meetings began. I enjoyed this as I got to know everyone a little bit before getting down to business. Once we got back from lunch, all of the members who taught a course last semester developing software for LibreFoodPantry had a retrospective detailing the good and the bad and developing ideas and solutions to the issues. I found this process interesting to observe, especially after learning about software management processes this spring and now I got to see it in action with a real project. My advisor and I briefly described our summer research project and how it relates to what was currently happening with LibreFoodPantry. Through the first day I began to learn about issues that the group was encountering and areas where I can focus my research. Some items I will need to look for is assigning issues to multiple people or groups.

Friday continued with the second day of the LibreFoodPantry Retreat. I came in after lunch and immediately saw a whole whiteboard along one wall covered in sticky notes with labels. I soon found out that this was all of the user story mapping that was worked on while I wasn’t there. Dr. Jackson went through the whole story mapping briefly with me, explaining the user groups and the features and how they all fit together. It was eventually decided that this story map should be stored in the LibreFoodPantry organization/group on whichever platform we end up using and I should try to create a small version of this board on each platform. We then moved on to discussing infrastructure and workflow. Additional things I will be looking at now will be setting up continuous integration in GitLab and see how this works. I will also be fixing my platform features table so that features have consistent naming with their respective platform and that they are directly comparable across rows. Overall, I really enjoyed going to the LibreFoodPantry Retreat and seeing the processes and discussions involved in creating an open source software project.

From the blog CS@Worcester – Chris' Computer Science Blog by cradkowski and used with permission of the author. All other rights reserved by the author.