Author Archives: Fadi Akram

Be the Worst

After looking at the list of Apprenticeship Patterns, the one titled “Be the Worst” caught my attention. I was curious as to why you would want to be the worst. After all, conventional wisdom would suggest that one should try to be the best. However, after reading about the pattern, being the worst is a way to become better. The pattern explains that you should aim to constantly surround yourself by developers that are better than you. By doing so, you would give yourself room to grow. Being in a strong team gives you an opportunity to learn the effective techniques, tips, and methods that stronger developers use. The goal is not to constantly remain the worst, but rather, to work hard to climb your way up from the bottom and become equal to the other members.

However, there are a few risks with being the worst. One of these risks is feeling bad about yourself and your skills. Being the worst member of the team means you are not up to par with everybody else, and that could lead you to become even less productive. Another risk that you could run into is dragging the team down. Being the weakest member, some teams might not tolerate your weakness for long, especially if you do not put in the effort to constantly improve and hone your skills. If you fall too far behind, then you risk getting fired. The way to avoid these risks is to make yourself useful by doing explicitly doing menial tasks and by developing concrete skills to increase the amount of your contributions. Rapid growth is what these teams want to see, and it is likely why you were hired to join them.

I think Be the Worst is a useful pattern. It gives a clear idea or a method as to how developers can grow professionally and actively hone their skills. While there are risks involved in being the worst, it can be avoided with a strong drive to improve and be a contributing member. The potential benefits of this pattern are immense and it should be something that every apprentice developer should look into.

From the blog CS@Worcester – Fadi Akram by Fadi Akram and used with permission of the author. All other rights reserved by the author.

Apprenticeship Patterns Chapter 1 and Chapter 2-6 Introductions

Chapter one of Apprenticeship patterns was quite the interesting read in my opinion. I think the chapter is overall very interesting, however I especially liked Dave’s story. I think his experience is somewhat like mine. I also tried to teach myself to code when I was younger, but my attempts were unsuccessful because I got easily overwhelmed. It was only when I came to college did I start properly learning a programming language, Java. I think having professors act as mentors that I could learn from and ask questions really helped me pick up Java. I think the authors really tried to emphasize how important mentors are to growth in this chapter, and I can’t help but agree based on my own experience. However, I wouldn’t call myself proficient in Java or any language. I feel like I just started scratching the surface of programming and I still have a lot to learn. I think that’s the takeaway from this story. In order to grow as a software developer, you need to be humble and open minded. You can never master software development or learn everything, there will always be room for improvement and new things to learn. This idea seems to be reinforced with the other chapters.

The emptying the cup story in the introduction of chapter two stresses the importance of having an open mind. Just like the young philosopher, we all need to empty our cups. We all need to make sure that we clear our heads of bad habits, setting aside our pride, and opening our minds to new and different things. I personally never thought of my previous experience as something that could hinder my learning, but after reading this emptying your cup story I can understand why that may be the case sometimes. Chapter three talks about the importance of learning. It talks about how learning gives you insight on much more you have to learn. There will always be exceptional people to take inspiration from and there will always be new things to pick up and learn. Chapter four adds on to the previous chapters by discussing the significance of ambition. The idea of growth shouldn’t be capped to being an average developer or an above average developer, but rather, to be a better developer than you were yesterday. Chapters five are similar to each other since they both talk about how an apprentice should grow their skills and knowledge. In chapter five, the emphasis was placed on practice and communication. You should practice what you learned so you can retain the knowledge and you should communicate your understanding to demonstrate the extent of your knowledge. Chapter six talks about how a good apprentice should read old fashioned books to increase their knowledge. Overall, the introductions of these chapters all complement each other, they all give ways in which a software developer can get better. I think these are all very useful, and it’s important for me to keep an open mind and learn from them.

From the blog CS@Worcester – Fadi Akram by Fadi Akram and used with permission of the author. All other rights reserved by the author.

Set Up Task 4: Thea’s Pantry

I looked through the documentation for Thea’s Pantry to get an idea of what the project is about and how the project works. Of the sections, the User Stories section stood out to me the most because I felt like that t gives an idea of how the project should work, what features it should have, who it is serving, and what the software architecture should look like. I think this guide is very helpful for future reference when working on the project myself. I think that it is something that I will revisit frequently to make sure that I am on the right track.

From the blog CS@Worcester – Fadi Akram by Fadi Akram and used with permission of the author. All other rights reserved by the author.

Set Up Task 3: LibreFoodPantry

After reading several sections on the LibreFoodPantry website, I found the Code of Conduct to be rather useful. It provides a very clear picture of what is expected and how things are handled in a simple, straightforward way. The page explains in detail what the goal is, what the community standards are, where they apply, how they are enforced, and how the violations are handled. I think it’s very important to understand and be familiar with the culture, values, and standards of the community before being a contributing member. I will try to visit this section every once in awhile to remind myself of what values and practices I should uphold when working on this project.

From the blog CS@Worcester – Fadi Akram by Fadi Akram and used with permission of the author. All other rights reserved by the author.

Blog post 7 –DRY and YAGNI

DRY and YAGNI are two acronyms used to describe best practices when it comes to coding. DRY stands for “Don’t Repeat Yourself” while YAGNI stands for “You Ain’t Gonna Need It”. These two acronyms or best practices complement each other very well. They both aim to make code cleaner, simpler, and free of coding smells such as needless complexity and needless repetitions. These are coding smells that every developer should avoid. So, what do they actually mean?

DRY or “Don’t Repeat Yourself”, is a best practice revolving around repetition in code. When it comes to code, quality is always better than quantity. Why have hundreds of lines of code when you could have a dozen lines that do the same thing? Having duplicated code or duplicated logic is a waste. Not only will you waste time and effort, in the beginning, adding the unnecessary code, but you will also waste further time and effort maintaining and extending the code in the future. Repetition in code can be caused by a variety of reasons mostly from either poor programming habits, like copy and pasting code without really understanding how it works, or from a poor understanding of coding knowledge in general, but specifically, a poor understanding of encapsulation. Regardless of the cause, needless repetition should be avoided as much as possible and repetitive code should be eliminated by refactoring wherever possible.

YAGNI is an acronym that stands for “You Ain’t Gonna Need It”. YAGNI is a coding best practice that stems from the principles of Extreme Programming or XP. YAGNI revolves around the idea of avoiding the writing of unnecessary code that is based on foresight rather than need. Martin Fowler describes YAGNI as “a statement that some capability we presume our software needs in the future should not be built now because “you aren’t gonna need it”. In other words, software developers should always implement features when they need them and never when they just foresee the need for them. There are several reasons why YAGNI exists. One very good reason is that it maximizes the amount of unnecessary work that is left undone. This is excellent because it improves the productivity of software developers, and it maintains the simplicity of products. Simplicity is especially important because implementing new features is quite expensive. It takes a significant amount of time, money, and resources to add the features and to maintain them. Features that are not necessary can be very costly. To avoid wasting resources on unnecessary features, apply the YAGNI principle and don’t implement features unless you need them now.

From the blog CS@Worcester – Fadi Akram by Fadi Akram and used with permission of the author. All other rights reserved by the author.

Blog post 6 – What is the difference between front end and back end development?

Front end and back end development get thrown around a lot, but I never really understood the difference. Therefore, I decided to do some research and figure out what front end development and back end development are, and what the difference between them is.

Let’s start with front end development. Front end development, also known client side development, deals with the user interface. The user interface, or UI for short, is what the user gets to see and interact with. Front end developers are responsible for designing and creating the user experience elements in a program. Front end developers may find themselves using technologies like Hypertext Markup Language (HTML), Cascading Style Sheets (CSS), and JavaScript to implement features such as buttons, menus, pages, and so on. The goal of front end development is to create attractive, simple, and easy to follow interfaces for users. However, achieving this goal can get quite complicated due to a major challenge. This major challenge is the sheer amount of variance in devices. Not all devices are the same. There are devices that are big and small, fast and slow, and new and old. Guaranteeing a consistent experience across all devices and platforms is a very difficult task but is an essential one. This gets further complicated with the rapidly evolving technologies, standards, and practices.

Now, back end development, as you might have guessed is the complement of the front end development. If front end development deals with things that the user can’t see then back end development deals with things that a user cannot see. Back end development, also known as server side development, deals with servers that provide data on request, the applications which channel those requests, and the databases which organize the information. Back end developers might find themselves using databases such as IBM DB2, MySQL, and NoSQL as well as a bunch of programming languages and frameworks such as Java, Python, and C++. The goal of back end development is to design and create applications that can accurately locate and deliver data to the front end as smoothly as possible.

While developers usually just specialize in either front end development or back end development, sometimes employers need developers who are proficient on both ends. This is known as full stack development, and these highly specialized developers are known as full stack developers. Their job is to use their deep knowledge to suggest ways to make the development process more efficient.

From the blog CS@Worcester – Fadi Akram by Fadi Akram and used with permission of the author. All other rights reserved by the author.

Blog Post 5 – SOLID Principles

When developing software, creating understandable, readable, and testable code is not just a nice thing to do, but it is a necessity. This is because having clean code that could be reviewed and worked on by other developers is an essential part of the development process. When it comes to object oriented programming languages, there are a few design principles that help you avoid design smells and messy code. These principles are known as the SOLID principles. These principles were originally introduced by Robert J. Martin back in 2000. SOLID is an acronym for five object oriented design principles. These principles are:

  1. Single Responsibility Principle – A class should have one and only one reason to change, meaning that a class should have only one job. This principle helps keep code consistent and it makes version control easier.
  2. Open Closed Principle – Objects or entities should be open for extension but closed for modification. This means that we should only add new functionality to the code, but not modify existing code. This is usually done through abstraction. This principle helps avoid creating bugs in the code.
  3. Liskov Substitution Principle – Let q(x) be a property provable about objects of x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T. This means that subclasses can substitute their base class. This is expected because subclasses should inherit everything from their parent class. They just extend the parent class, they never narrow it down. This principle also helps us avoid bugs.
  4. Interface Segregation Principle – A client should never be forced to implement an interface that it doesn’t use, or clients shouldn’t be forced to depend on methods they do not use. This principle helps keeps the code flexible and extendable.
  5. Dependency Inversion Principle – Entities must depend on abstractions, not on concretions. It states that the high-level module must not depend on the low-level module, but they should depend on abstractions. This means that dependencies should be reorganized to depend on abstract classes rather than concrete classes. Doing so would help keep our class open for extension. This principle helps us stay organized as well as help implement the Open Closed Principle.

These design principles act as a framework that helps developers write cleaner, more legible code that allows for easier maintenance and easier collaboration. The SOLID principles should always be followed because they are best practices, and they help developers avoid design smells in their code, which will in turn help avoid technical debt.

From the blog CS@Worcester – Fadi Akram by Fadi Akram and used with permission of the author. All other rights reserved by the author.

Blog post 4 – Semantic Versioning

One of the more interesting topics that we covered in class was semantic versioning. I found it interesting because it is something that I see all the time but had no idea what it meant. After reading over the documentation, I’ve learned that semantic versioning is a set of rules that dictate how version numbers are assigned and incremented. Semantic versioning was proposed as a solution to dependency hell, which occurs when you version lock or when version promiscuity prevents you from easily and safely moving your project forward.

Semantic versioning works in three parts, X, Y, and Z. They are usually written as X.Y.Z, as that is the form semantic versioning must take. Each component says a different thing about the version. The X states what the current major release is, the Y states what the current minor release is after the last major release, and the Z states what the current patch release is after the last minor release. What do a major release, minor release, and patch release mean?

A major release is the first part of the semantic versioning framework. It goes at beginning of the version number. A major release occurs when you make incompatible API changes. The changes must be backward incompatible in order to be considered major. A major version zero is for initial development, and anything may change at any time. When a new major update is released, the minor, and patch version numbers must be reset back to zero.

A minor release is the second part of the semantic versioning framework. It goes in the middle of version number.  A minor release occurs when you add functionality in a backward compatible manner. A minor release needs to be incremented every time any public API functionality is marked as deprecated. Minor releases could also be incremented if substantial new functionality or improvements are introduced within the private code, and it could include patch level changes. When a minor update is released, the patch version number must be reset to zero.

A patch release is the third and final part of the semantic versioning framework. It goes at the end of the version number, and it refers to an update that focuses either exclusively or primarily on bug fixes. A bug fix is a change made to the code to correct incorrect behavior. A patch release does not add any new features, it just modifies existing code to fix errors or make the code run the way it was intended. All the bug fixes must be backward compatible.

From the blog CS@Worcester – Fadi Akram by Fadi Akram and used with permission of the author. All other rights reserved by the author.

Blog post 3 – REST API

After spending some time in class working with the REST API, I found myself still having questions regarding what it is and how it works. I decided that I should do some further reading on my own, and I thought that I should make a blog post explaining my findings. I read several articles, but one article in particular by IBM I think describes REST API the best.

Before we delve into REST itself, we first have to understand what an API is. API stands for application programming interface; it is a set of rules that define how applications or devices can communicate with each other. It’s a mechanism that allows applications to access resources within other applications. The application that is utilized to access the other application is called the client, while the application that contains the resources being accessed is called the server.

REST API is an API that uses REST principles. Unlike other APIs which have pretty strict frameworks, REST is pretty flexible. The only necessary requirement is that the REST design principles, or architectural constraints, are followed. These are:

  1. Uniform interface – All API requests for the same resources should be the same regardless of where the request came from.
  2. Client-server decoupling – The client and the server need to completely independent of each other. The client should only know about the URI, or the Uniform Resource Identifier, and the server should only pass the client to the requested data via HTTP.
  3. Statelessness – All requests need to include all the information necessary to process them.
  4. Cacheability – Resources should be cacheable on both the client and the server. The server should also know whether or not caching is allowed for a delivered resource.
  5. Layered system architecture – The calls and responses go through different intermediary layers.
  6. Code on demand – Usually, REST APIs send static resources, but in some cases, they can also contain executable code. In such cases the code should on run on-demand

I didn’t know that REST API had design principles, so this was new information to me. However, so far, I only discussed what REST API is, we still need to understand how it works. REST APIs communicate using HTTP, Hypertext Transfer Protocol, requests to perform basic functions in databases like creating, reading, updating, and deleting data inside a resource. For example, a GET request would retrieve data, a DELETE request would remove data, a PUT request would update data, and so on. All HTTP methods are able to be utilized in API calls. Another thing to note is that the resource representation can be delivered to the client in virtually any form including JSON, HTML, Python, and even normal text files. Finally, it’s important to note the request headers, response headers, and parameters in calls. They’re important because they contain vital identifier information such as URIs, cookies, caching, etc.

From the blog CS@Worcester – Fadi Akram by Fadi Akram and used with permission of the author. All other rights reserved by the author.

Blog post 2 – Design Smells

In programming, we often make a lot of mistakes, some break the code, and some do not. The ones that do not tend to bring down the efficiency of our code and make it very difficult to work with. Some of these mistakes have to do with the way we write the code, and they tend to hint at a bigger problem in the code design. These mistakes are called design smells. I think Martin Fowler defines coding smells the best, he defines them as a “surface indication that usually corresponds to a deeper problem in the system.” Design smells come in all different ways, but they usually stem from developers not following best practices. The end result is that the code either becomes too bloated, too inefficient or breaks easily. Luckily, design smells are rather easy to spot once you know what they are. Some of the more common smells are:

Rigidity – Program breaks in many places when a single change is made to the code.

Immobility – The code contains parts that could be useful in other systems, but the effort and risk involved in separating those parts from the original system are too great.

Opacity – This smell occurs when the code is difficult to understand and follow.

Fragility – The code becomes pretty difficult to change. A simple change could cause a cascade of subsequent changes in dependent modules.

Viscosity –  When making changes to the code, it is easy to do the wrong thing, but hard to do the right thing.

Needless complexity –  There are elements in the code that are not useful. Having them in the code is simply not necessary and it makes the code more complex than it needs to be.

Needless repetitiveness –  There are too many repeating elements in the code that could be removed by using abstracted or refactoring the program.

These are things that we do not want in the code. In fact, they are considered technical debt. Technical debt is a term that describes the effects of mistakes or bad practices in code. As we program, we are going to make mistakes, errors, and sometimes not follow best practices. These shortcomings are things that we will have to revisit later today and spend time, resources, and effort spent on trying to fix and modify the code to make it work better. In this sense, it is similar to normal debt.  Once you know the smells, it’ll become a lot easier to find them in your code. If you do spot design smells, then it is best to try to remove and solve the underlying problem.

From the blog CS@Worcester – Fadi Akram by Fadi Akram and used with permission of the author. All other rights reserved by the author.