Category Archives: Week-15

Apprenticeship Patterns Blog – Retreat into Competence

For the last and final blog post in my capstone class, I focused on the apprenticeship pattern of “Retreat into Competence” from chapter two of the book Apprenticeship Patterns by Dave Hoover and Adewale Oshineye. The section talked about perhaps how you are overwhelmed or beginning to realize how little you know, or perhaps you have taken on a new challenge and things are not working out so well. However, getting back into something you are good at is a nice way of regaining your composure. I completely agree with this statement, sometimes all we need a just a pullback to launch forward towards the goal. The quote provided at the beginning of the section is what stood out to me the most. It states that “You look at where you’re going and where you are and it never makes sense, but then you look back at where you’ve been, and a pattern seems to emerge. And if you project forward from that pattern, then sometimes you can come up with something.” This got me thinking very deeply about the past four years of college and my CS Journey. I have no idea what the future hold, but one day I will look back to see where I have been and possibly see a pattern emerge.

The author also mentioned how apprenticeship is a roller-coaster ride, you will experience the thrill of new technologies, but you will also experience struggles as just how little you know compared to the craftsmen and experts you meet along the way. It is important that Sometimes you need to take one step back to take two steps forward. But it is essential to move forwards as quickly as possible because the forward momentum is revealed in your possession of more knowledge and greater skill than you had yesterday. Another important aspect the author mentioned is how to seek support from your mentors, with their support and boost you can be on the right track again and display competence. In this way, you will be more equipped for future challenges. The patterns displayed a lot of insights towards my career and on a personal level. I will certainly be reading more patterns from this book even though this is my last and final blog post for the CS-448 class.

 

From the blog Derin's CS Journey by and used with permission of the author. All other rights reserved by the author.

Use the Source Luke – Apprenticeship Pattern

In this post I will be discussing the apprenticeship pattern, “Use the Source” written by Adewale Oshineye and Dave Hoover in the book Apprenticeship Patterns: Guidance for the Aspiring Software Craftsman, 2009. This pattern is for people who have not developed in environments that have stressed the importance of the ability to read source code. Developers often spend much more time reading source code than actually writing it. Often times developers cannot understand the code and have to rewrite it themselves. As stated in the book, Bill Gates once said, “one of the finest tests of programming ability is to hand the programmer about 30 pages of code and see how quickly he can read through it and understand it”. People who can absorb design patterns, algorithms and data structures through real code become great programmers because they are learning from every good programmer each line at a time.

The authors suggest picking an algorithmically sophisticated open source project and take note of the algorithms, data structures, and design decisions made in the code that are new to you. Then, write a blog post for each new idea you learned. While doing this, download the lates version of the project and try to work out why the developers made certain decisions in the design and architecture and try to work out ways you would have done it. Figure out if your way wouldn’t work or would actually be a better solution. This will cause you to think deeper about the reason the project is coded the way it is.

I found this design pattern very interesting because I would agree that the ability to read code is very important and my lack of experience doing so has caused me lots of problems in the past. Often times I have had to rewrite code I was not able to understand or attempt multiple times to understand a piece of source code before finally getting it. I would say that I have improved, but there is still lots of room for improvement in the future. I like the idea of examining open source projects and I think I will do so very soon.

From the blog CS@Worcester – Austins CS Site by Austin Engel and used with permission of the author. All other rights reserved by the author.

Be The Worst

The section “Be The Worst”, found in chapter four in Apprenticeship Patterns by Dave Hoover and Adewale Oshineye focuses on situations where you aren’t able to learn much from your environment. Being on a strong team has its benefits, other members can cover areas where you are weak on and catch you before making mistakes among other things. Ideally, a team member should be able to take a step back from their team to accurately assess their skill and knowledge. In the case where the gap in skill or knowledge between yourself and other team members in vastly in your favor, then it’s likely that you won’t be able to grow much as a software developer. Because of this, it’s best to start out as the weakest member of a team, hence “Be The Worst”, in order to have room to learn and grow. Emphasis on “start out”; the weaker members of a team should work more to catch up to the rest of their teams. If they don’t bother, then the “Be The Worst” pattern kind of loses its whole point.

Fortunately, or unfortunately depending on how you look at it, I’ve never felt that I was the strongest in a team skill wise. Some of the people I’ve worked with on a team do things super quickly so I had to adapt by starting tasks early and refamiliarizing myself with certain concepts. I guess you could consider that a method of catching up with other team members. In a team setting, I don’t actively try to “Be The Worst” but I at the very least understand why it’s a pattern. If people aren’t challenged, then they’re tempted to stagnate and it becomes all too easy to end up as a big fish in a small pond. When someone better inevitably comes along, then those who’ve done nothing to improve are thrown for a loop and can’t easily adapt to that change. Though, people could also be motivated to do the opposite; work catch up or even surpass their peers in order to not be seen as the weak link.

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

Apprenticeship Patterns – Share What You Learn

The problem of this pattern is one of the final ones, as far as I can tell. It is framed around your near-completion as a developer. I mean this in the sense that you’re a rounded-out developer with a lot of useful skills, but not necessarily a significant amount of real-world experience. In order to truly become a journeyman, you need effective communication skills. It isn’t enough to be a good programmer.

In order to gain such skills, the proposed way is to share that which you have learned. One such way is via a blog such as the one you’re currently reading. I pretty much completely agree with this pattern. I think the best way to learn things is to explain them to someone else. Really, the reason that we are tasked to write large essays in high school and college, despite them being annoying, is because writing is thinking. If you are capable of reading these words, then you’re most likely literate. Modern people take literacy for granted. For millions of years, the vast majority of humans were illiterate and as such their brains developed in a different manner to ours.

According to a discussion with Psychologist Jordan Peterson (that I unfortunately cannot find to link here), illiterate people think differently than literate people. Illiterate people think more in images and experiences, similar to how animals think. (Don’t let your arrogance get the better of you; all humans are animals biologically.) Words themselves are abstractions and your brain has to handle abstractions differently. It has to convert from symbols and sounds to the word to the meaning of the word. I would say that tribes of people that rely heavily on the oral are similarly affected. Nonetheless, literacy has a profound effect on your brain and thus how you learn. Writing is a form of thinking. Literate people have the ability to write or type words without really planning it in their minds, similar to how people can speak without thinking. The words are the thinking. So, when you explain something, you need to find the words to describe it and that process is thinking.

That’s why written words can be so messy; we think through them as we write. Thoughts are messy. So, it is essential to be an effective communicator not only to benefit others. Ignoring the existence of other people, being an effective communicator means you are an effective thinker. This is specifically in terms of words, which I would argue programming requires. The concepts dealt with in programming require intense mental abstractions that most of us take for granted. There’s a reason the general population thinks coding is magic. It’s simply too abstract to fully grasp from a single viewing. This means words are the way we handle that abstraction. Thus, make yourself powerful with words in order to become powerful in your actions as a programmer.

From the blog CS@Worcester – The Introspective Thinker by David MacDonald and used with permission of the author. All other rights reserved by the author.

Apprenticeship Patterns – Practice, Practice, Practice

The focus of this pattern is the simple idea that practice makes perfect. The problem arises from the fact that every time we code, we’re practicing. We try new things, we make mistakes, and we learn. However, when the majority of our code is for work, making all of these mistakes is sub-optimal in numerous ways.

Similar to previous patterns, the proposed solution is to practice outside of work. Do coding exercises for fun and learn from them so when you go to work, you can make fewer mistakes. I would mostly agree with this. My biggest criticism is the same as in a previous pattern; not everyone has the time outside of work to keep working. Depending on the job, it would require a person to live and breathe programming. They would need to use their free time, which is intended to keep the individual sane as well as give their mind a break so they can keep coding the following day. This could have overall worse consequences. For example, I’m capable of coding for virtually eight hours straight and I have on occasion. However, I almost always feel brain dead afterwards. Sometimes, I need a few days off afterwards to be able to think about coding again. As an athlete as well, I can say do not underestimate the importance of rest.

That said, I fundamentally agree with the notion of purposeful practicing. I started teaching myself programming in middle school and it was really slow and hard. The times I learned the most were when I could follow a well-made guide to create something simple. As I developed as a programmer, however, I was more easily able to guide myself through these projects. When I learn a new language, I often create a primality test. It introduces me to io, iteration, efficiency, data types, etc. in a language. Often, I’m unsatisfied with the maximum size of a 64bit integer and I start trying to create a larger integer object that can run efficiently and store large integers. This leads to learning even more skills in a language. However, there are books of prime numbers that go into absurdity. These projects aren’t really meant to have a utility outside of making them. This is what the author means by deliberate practice. I’ve spent years teaching myself different technologies and the most successful ways have always involved some sort of practice project. If nothing else, they make you really good at researching.

From the blog CS@Worcester – The Introspective Thinker by David MacDonald and used with permission of the author. All other rights reserved by the author.

Rubbing Elbows

The section “Rubbing Elbows”, found in chapter four in Apprenticeship Patterns by Dave Hoover and Adewale Oshineye focuses on a learning technique similar to “Record What You Learn” pattern which I wrote about during week 12 of this semester. To “Rub Elbows” in this context means to sit next to a fellow software programmer and exchange ideas. This could range from simply talking to each other during a lunch break to peer programming which is when two or more developers physically sit side by side and collaborate while they develop software. In any such case as these, a software developer will likely pick up on the small micro-techniques that are too trivial to be covered during active teaching. However, these techniques can add up and significantly contribute to the development of a software programmer. And when even if one were to disagree with their peer’s methods, they at the very least have gained a new perspective to view from. The same can be said in the case where there’s a knowledge gap between peers, which forces both of them to take each other’s viewpoints into consideration.

Again, like the “Record What You Learn” pattern, I’ve experienced and used “Rubbing Elbows” to an extent. In recent memory, me and a peer have helped each other study and do the work in classes that we share. We weren’t able to physically meet up since the pandemic but we occasionally talk to each other online through discord. I remember one conversation where he mentioned Python and I didn’t really know much of the language so I asked him what separated that with programming languages like C and Java. That got me interested enough to the point where one of my final projects for this semester partly uses Python code. There’s also a pet project that I’m toying around with, something to do with chess; I’m kind of tempted to research more of Python so I can write the code entirely in that language. It’s not what I’d describe as a micro-technique, but it’s something that I picked up while “Rubbing Elbows” with a peer.

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

The Principle of Least Knowledge

As I was reading about coupling and cohesion, I also came across the Principle of Least Knowledge, which just so happened to be on our list of topics in the syllabus.

The Principle of Least Knowledge (or Law of Demeter) was first discussed in 1987 at Northeastern University. It states that an object should never now the internal details of other objects, which makes sense given the name. It is used to promote loose coupling in software designs.

The article also gives an example using 3 classes – A, B, and C. Each class has objects objA, objB, and objC. objA is dependent on objB, which in turn composes objC. In this scenerio, objA can invoke methods and properties of objB but not objC. Say C has a method M. If you make a objC called O, the Principle of Least Knowledge says O can access

  • The same object, i.e., the object “O” itself
  • Objects that have been passed as an argument to the method “M”
  • Local objects, i.e., objects that have been created inside the method “M”
  • Global objects that are accessible by the object “O”
  • Direct component objects of the object “O”

A code example is also given to illustrate the concept.

public class LawOfDemeterExample

    {

        //This is an instance in the class scope

        //and hence this instance can be accessed by any members of this class

        AnotherClass instance = new AnotherClass();

       public void SampleMethodFollowingLoD(Test obj)

        {         

            DoNothing(); //This is a valid call as you are calling a method of the same class

             object data = obj.GetData(); //This is also valid since you are calling a method

            //on an instance that has been passed as a parameter           

             int result = instance.GetResult();  //This is also a valid call as you are calling

            //a method on an instance locally created

        }

        private void DoNothing()

        {

            // Write some code here

        }

    }

After, an second example is given to illustrate what not to do.

var data = new A().GetObjectB().GetObjectC().GetData();\

In this example the client depends on all three classes A, B, and C. If any of the three change you will run into issues.

This principle will definitely be important as I continue my career in software development. As the ode I write gets more complex, I have to be wary of violating principles like this to maintain low coupling. The author also mentions testability being improved with this principle and the loosely coupled code it encourages. Next semester I am taking the software testing course; right now I have next to no knowledge about software testing. I only know how to just test units made for me in java. Hopefully I will see how loosely coupled code compared to tightly coupled code in testability.

From the blog CS@Worcester – Half-Cooked Coding by alexmle1999 and used with permission of the author. All other rights reserved by the author.

Coupling and Cohesion

This week I wanted to learn more about coupling. The article I found happened to be about both coupling and cohesion.

Coupling and cohesion are both terms that refer to the modularity in a system. They help measure how complex the design of an object-oriented system is. Good knowledge of both is needed to build scalable systems that can be extended and maintained over time.

Coupling is how interdependent software modules are. With high coupling, software modules are very independent, and they need each other to run. There are several types of coupling:

  • Content coupling — this is a type of coupling in which a module can access or modify the content of any other module. When a component passes parameters to control the activity of some other component, there is a control coupling amongst the two components.
  • Common coupling — this is a type of coupling in which you have multiple modules having access to a shared global data
  • Stamp coupling — this is a type of coupling in which data structure is used to pass information from one component in the system to another
  • Control coupling — this is a type of coupling in which one module can change the flow of execution of another module
  • Data coupling — in this type of coupling, two modules interact by exchanging or passing data as a parameter

Cohesion is how intra-dependent a software module is. High cohesion is a software module that forms its own meaningful unit. There are also different types of cohesion:

  • Co-incidental cohesion — this is an unplanned random cohesion that might be a result of breaking a module into smaller modules.
  • Logical cohesion — this is a type of cohesion in which multiple logically related functions or data elements are placed in the same component
  • Temporal cohesion — this is a type of cohesion in which elements of a module are grouped in a manner in which they are processed at the same point of time. An example could be a component that is used to initialize a set of objects.
  • Procedural cohesion — this is a type of cohesion in which the functions in a component are grouped in a way to enable them to be executed sequentially and make them procedurally cohesive
  • Communicational cohesion — in this type of cohesion the elements of a module are logically grouped together in a way that they execute sequentially and they work on the same data
  • Sequential cohesion — in this type of cohesion the elements of a module are grouped in such a manner that the output of one of them becomes the input of the next — they all execute sequentially. In essence, if the output of one part of a component is the input of another, we say that the component has sequential cohesion.
  • Functional cohesion — this is the best and the most preferred type of cohesion in which the degree of cohesion is the highest. In this type of cohesion, the elements of a module are functionally grouped into a logical unit and they work together as a logical unit — this also promotes flexibility and reusability.

Tight coupling makes maintenance difficult as all the components depend on each other.

This article was helpful in explaining these two concepts. As we develop increasingly complicated software in our courses and careers it is important to learn more abstract concepts. These were things I have never really thought about before. Usually I write code just so that it works. If I am going a step further I might try to make it “look good” and be neatly indented with as few lines as possible. Especially going into the capstone course, I will have to evaluate my code for things like low coupling and high cohesion.

https://www.infoworld.com/article/2949579/design-for-change-coupling-and-cohesion-in-object-oriented-systems.html

From the blog CS@Worcester – Half-Cooked Coding by alexmle1999 and used with permission of the author. All other rights reserved by the author.

Code Smells

For this post, I wanted to talk about code smells. I picked this topic since it was related to my software construction course, and I believe I could benefit from diving into it some more. In my course, I feel like I learned much more about design smells, but not as much relating to code smells. A code smell is a characteristic or surface indication that shows there may be a deeper underlying problem with a code. Typically, they’re easy to spot, but I wanted to learn more techniques to look for these problems. In the past, I’ve discussed refactoring, and this ties into that nicely. Learning more about code smells will allow me to become better at refactoring. In order to learn some more about code smells, I listened to episode 88 of the Complete Developer Podcast which was all about code smells.

In the podcast, the hosts discuss what code smells are, as well as methods and techniques to find code smells. I was already familiar with some of the smells mentioned in the podcast, which makes sense. I’ve been guilty of many of these as I first started learning code. Naturally, as you learn to code, refactor, and improve, you start picking up on some code smells, even if you don’t have an exact word or phrase for what the code smell is. I was much more interested in the podcast when they started discussing object-oriented smells, since this is much more relevant to what I’ve been studying most recently.

The most interesting smell I thought the hosts discussed was the Refused Bequest smell. Simply stated, refused bequest can occur when a subclass only uses a portion of properties and methods inherited from its parents. Unneeded methods can go completely unused or in some cases, give off exceptions. This is something I had never given much thought to, but it makes sense after hearing the hosts discuss it. I usually try to reuse my code as often as I can, so I could see myself making this type of error where I try to tie classes together through inheritance just to reuse my code. I’ve learned about delegation and using it rather than inheritance, but it’s not something I’m as comfortable with as I’d like. This segment in the podcast led me to go back and study delegation some more to improve my grasp on it.

From the blog CS@Worcester – Derek's Design by dereksspace and used with permission of the author. All other rights reserved by the author.

SOLID Design Principles

This semester, I spent a lot of time learning about object-oriented design. As my interest grew, naturally I wanted to learn more. In order to better my understanding of object-oriented programing, I listened to episode 142 of the Complete Developer Podcast on SOLID Principles. This podcast talks about about each of the 5 core principles of SOLID and how they’re implemented. The focus of SOLID is to make maintaining and extending code easier as a project grows. Proper use of SOLID design principles attributes to low coupling, high cohesion, and high encapsulation. It also helps to cut back on the need of refactoring, as well as avoiding code smells. SOLID stands for Single Responsibility Principle, Open-closed Principle, Liskov Substitution Principle, Interface Segregation Principle, and Dependency Inversion Principle.

The podcast reflects that SOLID design principles aren’t mandatory law, but rather should be utilized whenever they can to help improve code. The allow the code to be more flexible, but increase the complexity of the overall code. Personally, I felt that the Single Responsibility Principle was the most significant principle discussed in the podcast. To simply describe this principle, SOLID founder Robert C. Martin describes it as “A class should have one, and only one, reason to change.” In turn, following this principle can make software easier to understand and implement. Personally, this is something I tend to follow most of the time. However, there are times that I’ve tried to fit too many functions or responsibilities in a class. It doesn’t necessarily break the code, but I understand how it could make it harder to build off as the project grows.

I felt that many of these design principles tied into one another nicely in one way or another. For example, I could see a clear correlation between the Open-Closed Principle and the Single Responsibility Principle. The main idea behind the Open-Closed Principle is that objects and entities should be open for extension but closed for modification using object-oriented features such as interfaces, subclasses, and inheritance. While Single Responsibility Principle allows for modification to fix bugs, it explains how code can still be extended so long as each class has one sole responsibility. In this regard, I felt both design principles key emphasis is to avoid needless complexity. I think having this understanding now would have been beneficial for some of my prior classes, but I’m excited to have further knowledge of these tools to use in the future.

From the blog CS@Worcester – Derek's Design by dereksspace and used with permission of the author. All other rights reserved by the author.