Category Archives: Week 5

The Deep End: Taking off my floaters

The definition of many of the apprenticeship patterns in the book are all in their title, being fairly obvious or sharing language used in idioms or other expressions. However, despite this, our authors usually find a way to expand on them for at least a page or two – most often by sharing a relevant story. Which is why I was shocked at how brief this particular pattern was, just a handful of paragraphs and another for our story. The brevity of pattern however did not lessen its impact on me, and I have come away with a renewed confidence. As someone who needs structure in order to work effectively, I imagine the deep end would involve a great deal of work and specifically responsibility – which I respond to quite well also.

I had already determined to seek out an internship or entry level position outside of my home state. Further, I wanted to join a company where I, of course, could be actually hired but one that would truly test the limits of my skills. Ideally, I would want it to be an internship though, cause as much as I want to make this change in scenery, I’m still hesitant to get stuck someplace I’m miserable. I think the true test will not just be getting a position away from home but finding a place for myself in that new place and maybe even gaining the confidence to stay and accept a job at the company – in the case of an internship.

I did find one internship that states that they will make no “intern-work” and one should be expected to work as a peer with the rest of their fellow employees; and on a massively used and well-known mobile application no less. I jumped at the chance to apply for this position, and I am incredibly hopeful I get it, as it is the perfect storm of conditions I am hoping for. Enrique’s story is still a little too dramatic for me to imagine emulating, but I hope if the opportunity to work in another country even presents itself, I will have the confidence to take 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.

Apprenticeship Pattern Review 4: Retreat into Competence

When a software developer gets overwhelmed by the complexity of their current project or the fact that there is so much they don’t know, it is okay to “retreat into competence”. In the face of a challenge that seems insurmountable, taking a step back to see how for you’ve come and what you have accomplished is okay. While retreating into competence can be the right prescription for times like these, it is important to use the traction gained while retreating to propel yourself beyond where you first had stopped.

The title of this pattern almost seems contradictory to the whole concept of becoming a software craftsman. A software craftsman should always seek to move forward in their knowledge and career, why would the authors be telling us to retreat? While being able to continuously march forward indefinitely, steadily increasing project complexity and your responsibilities would be ideal, it almost never works like this in the real world. I find this pattern to be quite important, because without it, it seems that one would be going directly against the principles of a software craftsman to step back from a problem and retreat into competence.

One thing to note is I feel like it is especially easy to fall back on this pattern too much. If you consistently find yourself pressing the “eject” button whenever you reach a problem you might not know how to solve yet how will you ever go forward. It is important to set constraints on how long you can retreat in order to protect yourself from truly going against the principles of software craftsmanship and living a career filled with mediocrity. This is a powerful pattern, use it responsibly.

I feel like this pattern can be used in many situations in order to get over hurdles in one’s career that seem too great. Allowing yourself to create things you feel comfortable developing can help you regain faith in yourself and software development as a career. This is a pattern I have used myself and have seen great success with. When I find myself lost or over my head with a given problem, I like to solve small programming challenges, sometimes referred to as kata, in order to instill confidence in myself and remind myself how much I have improved over my career.

 

From the blog CS@Worcester – Your Friendly Neighborhood Programming Blog by John Pacheco and used with permission of the author. All other rights reserved by the author.

Breaking Toys

The Breakable Toys pattern talks about a familiar lesson in life, which is that you can learn from your mistakes and failures because they are bound to happen. The pattern suggests that you create something similar to what you are doing in your job/work and use it as a playground to see what will work and what won’t and expand on the things that interest you and learn from what you create or fail to create. The one thing they suggest making and that a lot of developers make is a wiki because they simple to make and expand upon over time to show what you have learned and what you are capable of.
This pattern seems very useful and something that I might implement very early into my career because it sounds fun and interesting. The ability to create something and build on is something that is very important especially in the world of computer science where new things are always being made/optimized. I think this pattern makes me feel like the ability to grow and work on what interests you is an extremely important quality to have in software development. I now understand why our professors wanted us to make a professional blog and use it later in our professional careers since it will demonstrate our interests and progress made in learning more about the different aspects of computer science and software development.
The one thing that I really like about this pattern is the creativity aspect because it makes learning more fun since you are adding and making things more refined because you want what you create to look or work better. The best projects, not only in computer science courses, were the ones that allowed us to create whatever we wanted and pursue what we were interested in. Treating a job like this can turn it from a boring and exhausting job to a hobby that you enjoy and get paid to do. I really like this pattern and wish I knew about it earlier because I most likely applied it to my computer science courses as well to make them easier and more fun.

From the blog CS@Worcester – Tyler Quist’s CS Blog by Tyler Quist and used with permission of the author. All other rights reserved by the author.

Docker and Automated Testing

Last week, in my post about CI/CD, I brought up Docker. Docker can be used to create an “image”, which is a series of layers that are built upon each other. For example, you can create an image of the Ubuntu operating system. From there, you can define your own image with Python pre-installed as a second layer. When you run this image, you create a “container”. This is isolated and has everything installed already so that you, or anyone else on your development team, can use the image and know reliably that it has all necessary dependencies and is consistent.

Of course, Docker will get much more complicated and images will tend to have many more layers. In projects that run on various platforms, you will also have images that are built differently for different versions.

So how does this apply to CI/CD? Docker images can be used to run your pipeline, build your software, and run your tests.

The company released a Webinar discussing how CI/CD can be integrated with Docker. They discuss the three-step process of developing with Docker and GitLab: Build, Ship, Run. These are the stages they use in the .gitlab-ci.yml file, but remember you can define other intermediate stages if needed. The power of CI/CD and Docker is apparent, because “from a developer’s perspective, all you have to do is a ‘git push’ — and that’s it”. The developer needs to write the code and upload to version control and the rest is automated, with the exception being human testers who give feedback on the deployed product. However, good test coverage should prevent most issues and these tests are more about overall experience.

Docker CI and Delivery Workflow
From Docker Demo Webinar, 4:49

Only five lines of added code in .gitlab-ci.yml are necessary to automate the entire process, although the Docker file contains much more detail about which containers to make. The Docker file defines the created images and the code that needs to be run. In the demo, their latest Ubuntu image is pulled from a server to create a container, on which the code will be run. Then variables are defined and Git is automated to pull source code from the GitLab repository within this container.

Then, a second container is created from an image with Python pre-installed. This container is automated to copy the code from a directory in the first container, explained above. Next, dependencies are automatically installed for Flask, and Flask is run to host the actual code that was copied from the first image.

This defines the blueprint for what to be done when changes are uploaded to GitLab. When the code is pushed, each stage in the pipeline from the .gitlab-ci.yml file is run, each stage passes, and the result is a simple web application already hosted from the Docker image. Everything is done.

In the demo, as should usually be done in practice, this was done on a development branch. Once the features are complete, they can be merged with the master branch and deployed to actual users. And again, from the developer’s perspective, this is done with a simple ‘git push’.

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

Exploring the Singleton Design Pattern

As we start to learn about more design patterns and their implementations in class, I wonder more and more about their application in the real world, as well as how they are perceived by modern developers. So far, for each design pattern we have learned, a relatively good job has been done in showing the advantages and pitfalls associated with them.

I became particularly interested in the Singleton pattern after finding the blog post: “Understanding What Singleton Pattern Costs You.” found here: https://blog.ndepend.com/singleton-pattern-costs/. There are also other sources I found that seemed to really dislike the Singleton design pattern, and I wanted to delve deeper into why that is.

In our in-class example with ducks, the Singleton solution seemed to make some sense for what we were trying to do. Rather than creating a new object every time we wanted our ducks to fly, we could have a single object and change its instance when needed. Because of the limited scope of what we were doing with the singleton pattern, we didn’t get a clear example of this practice potentially going south.

One way this can cause problems is that it can obfuscate code. Because a singleton is now essentially “global” and can be called everywhere, certain methods can do things that are part of this singleton that the method itself might not even indicate that it does. An example that the author of the blog provides is this:

In this example, the method is named BuildSimpleOrder, however, this method also logs the order. This makes it so you can make no assumptions about what your methods do, as many of them may have hidden behaviors. This has lead to a phrase that I have seen around tech blogs saying “Singletons are liars.”

This also causes problems in unit testing for similar reasons. Because you can use these singletons essentially globally, it can make it a lot harder to track problems in individual classes. This leads to high coupling. This also breaks the single responsibility principle – something that has been repeated in class a few times.

Learning about the different design approaches that we can take, with implementations evolving as the requirements change has been a good learning experience. It is becoming pretty clear that there is no “one size fits all” design and there can be advantages and pitfalls of each. However, I did want to do this deep dive on singleton, because I had seen it garner almost nothing but flak.

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.

Edge Testing

This past week in my Software Testing course I learned about edge Testing. I think when I was first learning about this subject I was more apt to lean towards boundary testing because my thought process was that everything that is supposed to work in a program should work and that’s what is important to test. Anything outside of that can just be blocked and is time consuming and tedious to check because those values will fail. However, I was intrigued by edge testing because it made importance in all values across the domain as well as out of bounds. I saw that it wasn’t enough to just assume the failures, you had to also know why they are causing a failure in order to combat them. Some problems are not easy to find but it is just as important to test the failures as it is to test the correct values and functions. Edge testing is a much more thorough and logical approach. This article was a nice pep-talk and helped persuade my thinking, check it out!

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

Refactoring or Adapting or … Both!

Refactoring is an inevitable location that all programmers reach eventually. Working on any project there is bound to be changes and new ideas or concepts on how to structure the code. With constant updates and inventions coming about everyday for the software world it simply is something we will all have to deal with. We create a program and find that we need to pass different parameter types to achieve a different outcome well now we have thirty plus methods to go back and change one by one. Now while that may be a necessary actions there is another concept to consider, that is adaptation! A good analogy of the Adapter Design Pattern is to consider a program is a cable you use to plug in an electronic device. Imagine that you travel to another country with your device and cable and now you run into the issue of a different wall socket. Your plug won’t fit even though it works just fine back home. Do you go out and buy a whole new wire to make it work with the new power source. No! Simply buy a wall adapter and your cable will work just fine(Of course you should check the voltage in real life, but the idea is the same). Perhaps there is nothing wrong with the structure of you code, you just need it to execute with different data types. By writing an adaptation class you could save a lot of frustration and time refactoring your original code. The adapter and adaptee could function by both implementing an interface and therefore the adaptee would only need to have an “implements … ” statement. In doing this you now have the ability to create any number of adapter methods instead of changing your original code. 

A nice simplistic example I found from an online article is that of the Rectangle class. Suppose you write a display() method to display the parameters of the rectangle to the user and the method expects the parameters x, y, w, h. However, the user wants to pass x1, y1, x2, y2 but this will cause an error in the display() method. If an interface is created that hold the display() method then if can be adapted in many ways and fix this issue.

My question to you is; do you think that adaptation is in fact refactoring. According to google the meaning of refactoring is “Refactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure”. Think about this, although I’m sure there is a clearcut textbook answer.

Design Patterns and Refactoring. (n.d.). Retrieved from https://sourcemaking.com/design_patterns/adapter.

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

Inversion of Control and Dependency Injections

When I started programming, one subject I felt I never fully understood was the Inversion of Control design principle, in the context of using dependency injection when testing. These were commonly mentioned in tutorials, blogs, and documentation. My main takeaway was “make it another class’s problem”, so I think it’s time for a refresher on this topic to see if that holds true. Inversion of Control extends the Dependency Inversion principle, the D in SOLID.

Once again Martin Fowler has a great article on the subject, this time with code examples. Before I summarize his description, what is the problem that IoC solves? A picture says approximately 2¹⁰ words, so:

A MovieLister depends on both the Abstraction and Concrete Class
From https://martinfowler.com/articles/injection.html

Fowler describes a MovieLister class that can act on the MovieFinder interface. This is great for the methods in MovieLister and makes it easy to modify, but MovieLister is also creating the implementation. It would be nice to change the implementation without modifying MovieLister, especially if we want to package MovieLister for use by others, who might need a different implementation of MovieFinder.

“We would prefer it if it were only dependent on the interface, but then how do we make an instance to work with?”

Martin Fowler, Inversion of Control Containers and the Dependency Injection pattern

The basic idea is simple: create the implementation of MovieFinder in another class and “inject” it into the MovieLister. This can be done in a separate Container class, or an Assembler class.

A class acts to assemble the MovieLister by creating the concrete implementation and injecting it to MovieLister
From https://martinfowler.com/articles/injection.html

Dependency Containers allow you to keep track of the classes that you must create and their dependencies. This container will construct the dependencies, create the object you need, and return said object. This isolates all changes to dependencies into a single class. Note that this is encapsulating what varies. The user only needs to decide on concrete implementations in their own custom Container. They can implement MovieFinder in a custom class and use in in their Container.

There are three types of dependency injections: constructor, setter, and interface. The difference is straightforward: either inject the dependency with a constructor at instantiation, a public setter method, or an interface method. Fowler prefers constructors and I’m inclined to agree. If possible, it is better to have a completely constructed object immediately.

I do think this really boils down to “make it another class’s problem”, but this phrase was misleading to me a few years ago. The problem I had with it was figuring out where to end the abstraction and create a concrete class, thinking it should be yet another class’s problem. It was tempting to misuse the design pattern, which left me feeling confused when I didn’t have a good answer. At some point, you need a concrete class to actually do the work. With this design pattern that concrete class is the Dependency Container.

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

UML Diagrams

During the first week of my CS 343 class we were learning about reading and writing uml diagrams. I found a article on lucid chart called UML Class Diagram Tutorial which was a big help. Its URL can be found below for anyone who is interested. It talked about hiw “Class diagrams are one of the most useful types of diagrams in UML as they clearly map out the structure of a particular system by modeling its classes, attributes, operations, and relationships between objects”. It also said how a class is made up of three block the top being for the name of the class. It also says how the middle is for attributes such as class variables. It also says how the bottom is for all the methods of the class. It also talks about the member access modifiers like how public is a “+” and private is a “-” and and static is underlined . It also talked about some I did not know about from class like how protected is “#” and package is “~” and derived is a “/” . It also talked about how to do Interfaces and Enumerations. It also had some good examples of them. Most of this though I already understood. What really helped me was the explanation of the different connections between classes and interfaces and such. It said how Inheritance is “the process of a child or sub-class taking on the functionality of a parent or super class, also known as generalization. It’s symbolized with a straight connected line with a closed arrowhead pointing towards the super class” and had an example. This connection I was not to bad with already though. What really helped me was the explanation of association and why only one side had a arrow on it sometimes which I had trouble with in class. The first type that was talked about was a Bidirectional association. They said this was “ The default relationship between two classes. Both classes are aware of each other and their relationship with the other. This association is represented by a straight line between two classes.” The second one they talked about was a Unidirectional association they said this was “a slightly less common relationship between two classes. One class is aware of the other and interacts with it. Unidirectional association is modeled with a straight connecting line that points an open arrowhead from the knowing class to the known class.”. I really learned a lot from this article and will continue to refer to it in the future if I need to be reminded about how to write a UML or how to read one.

https://www.lucidchart.com/pages/uml-class-diagram

From the blog CS@Worcester – Tim’s Blog by therbsty and used with permission of the author. All other rights reserved by the author.

Observe!

In many programs there will be an action taken only when something else has changed. For example, if there was a security app, you would not want it to continuously send you alerts that everything is fine, only when there is an actual emergency. This is where observers come in handy and in specific observer design patterns. Imagine you were creating an alarm system for inclement weather. Whenever there was inclement weather, an alarm would sound, a alarm message would appear on a phone, etc. Without observers, a person would need to run a clock that constantly checks for updates in the weather. By doing so in this process, there is a big strain on hardware. Observers send a signal when there is an update and does not require the constant checking for updates. When using observers, the design pattern should be set up such that there exists an interface called subject. This subject interface will be used to register and unregister observers, notify observers and get an update from the subject. The next interface will be the Observer interface which will contain an update method for the observer and a setSubject method, which is used to attach the subject to the observer. From here you will be able to implement these two interfaces. While implementing the Subject interface you will be able to create a class that overrides register, unregister and update the observer. When implementing the Observer interface, you will be able to override the update which allows for you to implement what the observer needs to be checking for. This allows for the user to have control over what the system is checking for. When that observer notices a change, it will be able to send a signal down to whatever class has extended subject and send out whatever notice must be sent when this event is triggered. By using this type of design pattern, the user is allowed to be very flexible while saving strain on the hardware that would normally be placed there by clocks. Many API’s use this type of design because as mentioned before, if an API had to have a clock running that was checking if someone had pressed a button every so-often, it would be chaos. The API is able to implement an observer for the buttons and when that button is pressed it updates the subject and executes whatever that button was programmed to do. This website gives a great breakdown of the design pattern and how to implement it.

Observer Design Pattern in Java

From the blog CS@Worcester – Journey Through Technology by krothermich and used with permission of the author. All other rights reserved by the author.