One thing I found interesting was the scope of the architecture, with it being composed of systems, and with each system having different features. What seems relatively simple requires many components that all have to mesh and interact with each other to form a cohesive whole. In particular, I found the diagrams to be very interesting, seeing the components that the different systems are composed of, and how those components interact within the system. I found this to be the most interesting because it related to what we did last semester, with the frontend and backend, and here is them being used in an actual practical, working system. It’s because it seems somewhat familiar to me, even though I don’t know the exact workings of the components, but because I know their overall function.
One thing I found interesting from the reading was the Agile values and principles, and the Twelve Principles of Agile Software. I found this interesting because it puts people and teams before the product, encouraging communication and teamwork over raw productivity. I found this interesting because I would have thought that everything would be based around getting the most productivity, but instead it emphasizes the process and making interaction within the team as smooth as possible. I really like the policy of responding to change rather than following a plan, because even though having a plan is great, sticking with a failing plan is most often a bad idea. I chose to write about this because this stuck out to me as good, common-sense practices that it seems often aren’t used.
Resource Link: http://www.kamilgrzybek.com/design/grasp-explained/
For this blog post I wanted to explore the GRASP principles. GRASP is an acronym for 9 principles that apply to object oriented design in programming, and it stands for General Responsibility Assignment Software Patterns. The 9 principles are: Information Expert, Creator, Controller, Low Coupling, High Cohesion, Indirection, Polymorphism, Pure Fabrication, and Protected Variations.
First, the Information Expert principle states that an object should have all the functionality and logic that pertains to it. For example, if a class has a list of objects, then it should also have all the logic for functions that pertain to that list, such as adding items, removing items, etc.
Next, the Creator principle states that an object should be created within the scope where it’s used. This means that if a certain class A relies on another class B to function, and B is unique to A, then B should be created within class A.
Next, the Controller principle states that the first object behind the front end UI layer should control the backend operations. This helps to separate the front end functionality from the backend functionality.
Next, the Low Coupling principle states that objects should be designed in such a way to where they can be isolated and reused without changing many other components. This helps to avoid rewriting code that could be useful in multiple places, instead making it generic so that it can fit into many different applications.
Next, the High Cohesion principle states that objects should only contain data and functionality that pertains to their function. This helps to avoid overloading a class with extraneous information and logic that isn’t necessary and should be abstracted or put into another class.
Next, the Indirection principle states that instead of directly coupling two objects, an intermediary object should be used between the two to handle the coupling. This helps to avoid a direct dependence relationship between two objects, instead having them both rely on an in between class that handles the relationship, so that change can be localized to that one class.
Next, the Polymorphism principle states that objects should be generalized so that they can handle support for different object types. For example, an animal class would have functions that pertain to all animals, and then subclasses could have functions that are more specific to certain kinds of animals.
Next, the Pure Fabrication principle states that shared functionality between classes should be placed within a separate class rather than in a class that it only roughly fits into. This helps to abstract functionality that could be repeated among many classes, instead putting it into a single shared class.
Finally, the Protected Variations principle states that systems that are likely to change should be protected as to not affected other systems. This helps to avoid breaking systems that other systems rely on, instead making sure that systems which other systems have a dependence on are protected and not susceptible to change.
For this blog post, I wanted to delve into what the SOLID principles are and how they apply to object oriented programming. SOLID is an acronym for the 5 object oriented design principles. They are the single-responsibility principle, the open-closed principle, the Liskov substitution principle, the interface segregation principle, and the dependency inversion principle. The reason these principles are important, and why they’re important to use is that they help to maintain good coding practices and help to avoid code smells. This is essential in large projects, as code smells and bad design could increase development time, make refactoring harder, and make development harder for teams if other team members couldn’t understand the code.
The first principle of SOLID is the Single-Responsibility Principle. It states that a class should have only one reason to change, and that it should have only one job. This means that a class should only have code related to its function, and not extraneous code that should be elsewhere that’s unrelated to the class’s intended purpose. This helps to keep classes simple and easy to understand. If a class contained logic unrelated to its purpose, then it would make the intended purpose of the class confusing.
The second principle of SOLID is the Open-Closed Principle. It states that a class should be open for extension but closed for modification. This means that a class should be designed in such a way that if a modification to that class is needed, it can instead be extended by a different class, and then that class could be modified while maintain the functionality of the original class. The also helps the make each class have its own specific purpose. If instead of creating a new class, a single class was modified every time a modification was needed, then the class would get messy very fast, making it hard to read and hard to understand its functionality.
Next, the Liskov Substitution principle states that every subclass that extends another class should be substitutable for the parent class. This means that for example, if there was a shape class, and then a square class extended the shape class, then the square class should be able to be used in place of the shape class.
Then, the Interface Segregation Principle states that classes shouldn’t be forced to use an interface which has functionality that it has no use for. This means that if an interface has some functionality that doesn’t apply to everything, then a class shouldn’t use that interface if it won’t be using that functionality. Instead, interfaces should be very broad, making them applicable for many different purposes.
Finally, the Dependency Inversion Principle states that functionality should depend upon abstractions, not concrete methods. This means that if you have a class that must perform some functionality, and it shouldn’t depend on an exact implementation, then the class must be design in such a way that it applies to all implementations, based off abstractions.
For this post I wanted to explore and delve into what exactly docker images are, how they’re composed, and how they’re interpreted within docker. I wanted to investigate this topic because while I understand at a high level how docker images work and what they’re used for, I don’t have a deeper understanding of their exact functioning and inner workings. My goal is to attain a better understanding of docker images so that I may understand the full scope of their functionality and uses. The purpose of this is so that I can better make use of docker images, because while right now I can use docker images just fine, I can’t utilize the more advanced functions and uses of them.
Basically, a docker image is a template that has instructions for creating a docker image. This makes it an easy way of creating readily deployable applications or servers that can be built instantly. Their pre-packaged nature makes it easy for them to be shared amongst other docker users, for example on a dev team, or to make a copy of a certain version of an application or server that’s easy to go back to or redistribute. In this way, Docker Hub makes it easy for users to find images that other users have made, so a user can just search for an image that fits their needs and take use of it with little to no configuration needed.
A docker image isn’t one file, it’s composed of many files that can be composed to form a docker image. Some examples of these files are instillations, application code, and dependencies that the application may require. This plays into the pre-packaged nature of a docker image, as all the code, instillations, and dependencies are included within the docker image, meaning that a user doesn’t need to search elsewhere for the dependencies required to configure a docker image. This also creates a level of abstraction, as all the user needs to know is the image that they want to use, and how to configure it, but they could have little knowledge of the code, instillations, or dependencies required for that docker image because the image handles it all automatically.
The way to build a docker image is either through interactive steps, or through a Dockerfile. For the interactive steps they can be run either through the command line or compiled into a single file that can be run to execute the commands. For a Dockerfile, all the instructions to build the docker image are within the file in a similar format for each image. There are advantages and disadvantages to each of the methods, but the more common and standard way is through a Dockerfile. With a Dockerfile, the steps to build a docker image are similar and repeatable for each image. This makes it easier to maintain within the image’s lifecycle, and it allows for easier integration into continuous integration and continuous delivery processes. For these reasons it is preferable for a large scale application, often being worked on by multiple people. The advantages of creating a docker image through interactive steps is that it’s the quickest and simplest way to get a docker image up and running. It also allows for more fine tuning over the process, which can help with troubleshooting. Overall, creating a docker image with a Dockerfile is the better solution for long term sustainability, given that you have the setup time required to properly configure a Dockerfile.
For this week I decided to research and write about what exactly docker is and what it’s used for in commercial applications or projects. With how much we use docker in class, I was curious as to what its other applications were and how it was used it other settings. I was curious about this because I had never heard of docker or used docker before this class, and it seems like such a useful and important piece of software. Even with just what we’ve covered so far in class, it appears to be very versatile and suitable to a variety of different applications.
This article summarizes what docker is, when and how it originated, the benefits of docker, and when and when not to use docker. I chose this article because it provides all the necessary information in a clean and concise way. While many other resources about docker were bloated and included lots of unnecessary information, this one has just the right amount of information to inform a user about what docker is, how to learn more about it, and how to get started using it. This makes it a great resource for someone new to docker, who maybe just heard about it and doesn’t know exactly what it is.
First, the article provides details about what docker is and when it was released. Docker was released in 2012, and since has become an important technology in web development. This was surprising to me because I figured I would have heard about such a big and important technology in web development, at least in one of my other classes. I figured that since I hadn’t heard of it, it must be a newer technology, but it’s already 9 years old. However, it does make sense that it would be a fast growing piece of software because of its versatility and ease of use. It makes the process of setting up and configuring a web server much simpler than it would be otherwise, and it makes monitoring those web servers easy through the docker application.
Next, the article delves into some of the benefits of docker. The benefits include reproducibility, isolation, security, docker hub, environment management, and continuous integration. Docker is reproducible in a similar way to a java application, because whereas a java application runs on a java virtual machine that is the same across all operating systems, a docker container runs in docker and is the same across all operating systems. This is very useful because it means that the container doesn’t have to be changed across different operating systems, meaning that setup time is reduced. Then, isolation is the property of a docker container where it can have instillations independent of the operating system it’s on, and independent of other docker containers. This helps to avoid conflicts between docker containers that may require different dependencies or installations. Next, with the different parts of an applications separated into different docker containers, security is increased. This is because if a single docker container is compromised, other docker containers won’t be affected. Also, different containers means that different versions of a project can be maintained independently, for example for testing. The docker hub makes it easy to find and use certain images, also leading to ease of setting up a docker container. Finally, docker can be used as a part of tools like Jenkins, meaning that when an update is made, it can automatically be saved and pushed to docker hub as an image, and put right into deployment. This cuts down on development time, and increases the ease of use by reducing the amount of work that must be done manually.
Resource link: https://flylib.com/books/en/4.444.1.47/1/
This week I decided I wanted to learn more about the different design smells. I understood the definitions from the activities in class, but I wanted to learn more about what exactly each design smell meant, and how to avoid them. I think it’s important to learn about the design smells so that you can know to look out for them when working on a project yourself. This is because accidently implementing one of the design smells into your code could lead to a lot of difficulty and frustration if you ever need to make changes later. For this reason, it is best to actively try and avoid them to ensure that whatever code you write will always be easy to modify and maintain.
This resource sums up exactly what each of the design smells is, why it’s bad, and what the consequences of implementing the design smells are. I liked that it uses practical examples and analogies to make the concepts explained easier to understand. While the concepts may be hard to understand because of how abstract they are, when broken down or applied to a situation everyone knows, it makes it much easier to get a grasp on what is being explained.
The resource breaks down into sections, each describing a different design smell. The first one is rigidity. Rigidity is described as when code is difficult to make even small changes in. This is bad because most often frequently code will need to be modified or changed, and if it’s difficult to even make small changes such as bug fixes, then that’s a very large issue that must be addressed.
The next design smell is fragility. Fragility is almost similar to rigidity in that it makes it difficult to make changes to code, but with fragility it is difficult because the code has a tendency to break when changes are made, whereas with rigidity things don’t necessarily break, but it is designed in such a way to where changes are very difficult to make.
Next, immobility is the design smell where a piece of code is immobile because it could be used elsewhere, but the effort involved in moving the code to where it could be useful is too hard for it to be practical. This is an issue because it means that instead of being able to reuse a piece of code, you have to write completely new code. That means that time is wasted when it could be used for more important changes.
Next, viscosity is the design smell where changes to code could be made in a variety of different ways. This is an issue because it means that time might be wasted deciding on what implementation of a change should be made. Also, disagreements might happen about how a change should be made, meaning that a team won’t be able to work towards the same goal.
The next design smell is needless complexity. Needless complexity is usually when code is added in anticipation of a change that might need to be made in the future. This could lead to bloated code that has many features that aren’t needed or aren’t being used. It is best to add code only when it’s needed to avoid this, and to reduce the overall complexity.
Next, needless repetition is the design smell where sections of code are repeated over and over, rather than being abstracted. This leads to code being hard to change or modify because it has to be changed in many different locations, instead of just one if it were abstracted. This is the benefit of abstraction, that a code modification that changes a lot of how it functions can be changed by altering code in one location.
Finally, opacity is the design smell where code is written in a way that’s hard, or difficult to understand. A piece of code could be considered opaque for a number of reasons, but in general it is when code that is understandable to one person might not be understandable to others. To avoid this, code should be written in a clear and concise manner that is easy to trace and understand, no matter who is working on it.
Hi, I’m Alex Nelson and I’m in my senior year at Worcester state as a computer science student. I’m excited to be going back to in person learning this semester because I prefer it over online learning. This blog exists as a means to share about my experiences related to computer science in college and related to my progression in learning in the field.