Category Archives: WSU

Apprenticeship Patterns Blog

Apprenticeship Patterns: Guidance for the Aspiring Software Craftsman by Dave Hoover and Adewale Oshineye is a book covering a comprehensive overview of software testing meant to prepare the reader with the knowledge and skills necessary for working as a quality assurance tester.

In the beginning of the book, Hoover and Oshineye answer the important questions of “what” is software testing and “why” it is necessary in software development.

At the highest and most general level, software testing is a way by which a software’s quality is evaluated, estimated, and shared with stakeholders, providing an independent view of the software product. Furthermore, it is the goal of software testers to ensure that this quality meets and maintains the requirements. I found it interesting that the book mentioned the primary function of software testing to be for the stakeholders; however, it makes sense as software testing not only is needed to ensure that the program runs, but also that it runs smoothly for the user, and most definitely for its stakeholders. The best way to assure stakeholders of the product’s success is through software testing.

Chapter two of the book gives further reasoning for software testing stating that the U.S. government lost 60 billion dollars due to software defects in 2002, equating to 0.6% of the country’s gross domestic product. In a world that is so heavily dependent on technology, it becomes evident how important it is to ensure that this backbone of society remains reliably working.

So with the question of “what” and “why” out of the way, the book shifts gears into the essence of software testing. The fundamentals of software testing is split into three parts: testing basics, requirements, and test plans.

The most basic form of testing is checking expected output with the observed output based on a controlled input allowing for a clear comparison and analysis of the program’s behavior. Most patterns of software quality assurance are based on this fundamental strategy.

Before testing software, it is necessary to know what it is that needs to be tested. This is given by the software requirements. These specify exactly what it is a specific piece of software should do under certain conditions ensuring that developers know what to build and that testers know what to test. Requirements are laid out in a test plan, a collection of test cases ensuring that every requirement of a software is met.

Software testing is complex field with many moving parts. However, it all boils down to ensuring that the program works as intended, meeting all the requirements and expectations shared by stakeholders and users, which saves time and money for companies that use it effectively. It is a field of software development that I am very interested in and am excited to learn about more.

From the blog Stories by Namson Nguyen on Medium by Namson Nguyen and used with permission of the author. All other rights reserved by the author.

Strategies of Behavior Testing

There are many kinds of software testing, behavior testing is one of the more common types. Behavior testing involves a thorough evaluation of a code’s behavior through a controlled testing of inputs. By evaluating the outputs, the developer is able to verify that software is working as intended, to fix the bugs if not, and by doing so ensure that the program meets user requirements.

Because of the numerous scenarios in which a program may be used, it is important specifically in behavior testing to evaluate the code a thoroughly as possible. There are multiple ways to do this. In the blog “What is Behavior Testing in Software Testing?” from codiumAI, five main types of behavior testing strategies are covered. I will share the top three that I found the most useful and interesting.

  1. Functional Testing

    This is a foundational testing type and used in practically every type of testing not just behavior testing. In the context of behavior testing however, the goal of functional testing is to verify that the software performs the specified functions and actions as needed.

    Specifically, functional testing aims to guarantee that the program complies with functional requirements, and when given certain inputs, that it generates the expected outputs. This can be done at the unit or system level to ensure that not only the software as a whole works, but also each individual component of code.

  2. End-to-End Testing

    After all the parts of a program are thoroughly individually tested, the next important step is to test how well all the parts work together to run the entire program. This is the purpose of end-to-end testing. The developers examine the flow of the entire program to make sure that all data and information are passed down through each module correctly and that there is seamless connection between each system.

  3. Usability Testing

    This type of testing is focused more the user experience. Usability testing, as the name suggests, focuses on the software’s user interface and overall user satisfaction. So, instead of checking for code bugs or input/output requirements, developers doing this type of testing are on the lookout for usability issues, poor layout, confusing navigation, or unclear instructions.

    Usability testing ensures that the application not only runs correctly but is also intuitive and pleasant to use at the business/consumer level.

Out of the three strategies of behavior testing, I found usability testing the most interesting because it reminded me that the best applications are the ones that not only do their job, but also do it in an intuitive, user-friendly way. So as someone who is looking to so into software development, it is important to remember to look at the code from a user’s perspective, especially when doing software testing.

Blog: https://www.codium.ai/blog/what-is-behavior-testing-in-software-testing/

From the blog Stories by Namson Nguyen on Medium by Namson Nguyen and used with permission of the author. All other rights reserved by the author.

Set-Up Post | Libre Food Pantry & Thea’s Pantry

Libre Food Pantry (LFP) and Thea’s Pantry are both organizations working to provide solutions to those in need by offering alleviation in grocery and other personal needs.

The LFP is developed mainly by instructors and their students who act as LFP Shop Manager and the LFP Shop respectively. Each Shop is further divided into Teams that work to develop and improve solutions.

Shop Managers are not only in charge of their shop and are also members of the Coordinating Committees whose responsibilities are to guide the direction of LFP, represent its high-requirements, support all the Shop Managers, and when appropriate, set necessary policies.

Thea’s Pantry is partners with Libre Food Pantry which is why I found it useful to learn more about how the LFP was organized.

One thing I found interesting about Thea’s Pantry was it’s relation to the Worcester County Food Bank. The pantry sends monthly reports using the Monthly Report system, which is accessed by a Pantry Administrator who specifies the month and year to generate the respective report as a downloadable Excel file.

For this reason, it is important to create a system that is able to reliably log and store activity records of the pantry about both the guests and inventory of the pantry. That is what the collaboration between Thea’s Pantry and the LFP wish to accomplish.

Knowing these facts allows me to see more clearly what I will be contributing to through my Capstone project, as well as the connections that allow it to happen.

From the blog Stories by Namson Nguyen on Medium by Namson Nguyen and used with permission of the author. All other rights reserved by the author.

Writing Clean Code in Python

At Worcester State University, I have been learning about programming through the context of Java. However, there are many other programming languages aside from Java. Though they likely follow the same principles and patterns, there are also inevitable differences, or at least a different approach to these same principles or patterns in practice.

The article Best Practices to Write Clean Python Code written by vanigupta20024 goes over Python specific clean code practices. The author presents four main tips:

  1. Clean indentation
  2. Using virtual environments
  3. Modular code
  4. “Pythonic” code

Clean indentation was taught in class under the context of “horizontal openness” or “horizontal spacing”. This principle is necessary for all languages, but it is especially necessary for Python. Python does not use braces to specify code blocks. Instead, it relies solely on space and tab indentations. Because of this, not only is clean indentation required to readable code, it is required for executable code!

Using virtual environments is something specific to Python. It allows the programmer to create a separate and custom environment for their project where any installed libraries and packages are separated from those installed outside the environment. That way, dependencies can be easily shared and managed separately for each project. Instead of having someone install libraries one-by-one, it is much cleaner to have the person run a requirements.txt file to automatically install all the necessary libraries and packages to run the code in one execution.

Modular code is a tool in Python that helps programmers follow the DRY principle (Don’t Repeat Yourself). This makes code clean by allowing programmers to create something like a code library that can be imported and implemented into the Python program without having to have all the code in the repository. Even better, modules can be uploaded into the Python database to be accessed by anyone, meaning that instead of having to create the function themselves, programmers can simply import the function they need to use in their code, making the code less dense and neater.

“Pythonic” code refers to special Python shortcuts that can make code easier to read by simplifying a task that would normally take multiple lines of code. For example, when swapping values, a programmer might initially think to write code this way:

value_a = 5
value_b = 6
temp = 5

value_a = value_b
value_b = temp

However, that is a lot of lines simply for swapping two values with the addition of a third variable. Instead, there is Python shortcut for this that simplifies the process.

value_a = 5
value_b = 6

value_a, value_b = value_b, value_a

Clean code is definitely an aspect of programming that I want to become more adept with. Python is not a language taught at WSU, but it was the sole language I used in my internship and research projects which is why I decided to do research on tips and tricks for clean code through the context of Python programming.

Source: https://www.geeksforgeeks.org/best-practices-to-write-clean-python-code/#

From the blog Stories by Namson Nguyen on Medium by Namson Nguyen and used with permission of the author. All other rights reserved by the author.

Adhering to the Law of Demeter

Also known as the Principle of Least Knowledge, the Law of Demeter states that objects should avoid accessing data and methods that belong in other classes and instead, only interact with its immediate dependencies (Baeldung).

When used with Object-Programming languages, the goal of the Law of Demeter is to make the components of a program less dependent on each other, loosely coupled, and therefore easier to manage and scale.

There are five rules to the Law of Demeter:

  1. The first states that methods should only call methods that belong to their same class. It is not recommended for a method in class X, for example, to call on another method in class Y.
  2. The second rule expands on the first to say that methods of a class should only call methods that belong to the objects created by that class. For example, a method X of a class Z should only call methods of an object created by method X.
  3. The third rule states that a method should only ever interact with an object when passed to it as an argument. There should be no direct access to the object within the method itself.
  4. The fourth rule allows the method of a class to invoke the method of a class given that it is an instance variable of the same class. For example, method X of class C is allowed to call the method of an object held as an instance variable of C.
  5. The fifth rule is similar to the fourth rule except it states that the method of a class is able to call the method of a static field in that same class, similar to a method of an object of the same class.

When these rules of the Law of Demeter are applied, they help prevent code from becoming tightly coupled, meaning that they cannot operate independently. However, there are some exceptions to certain cases such as for chain calling, fluent APIs, or working with data structures. An experienced programmer will know when and how to effectively apply the law of Demeter.

While refactoring the code for one of my research projects, I had practiced to apply the GRASP principles to the new design. For another project that I am refactoring, now that I am more comfortable with the GRASP principle, I will focus more on applying the law of Demeter to make sure my code is not tightly coupled. This means code that is less fragile, scalable, and easier to manage.

Source: https://www.baeldung.com/java-demeter-law

From the blog Stories by Namson Nguyen on Medium by Namson Nguyen and used with permission of the author. All other rights reserved by the author.

The 9 Principles of GRASP | Part 2

There are many parts that make up well designed code. One of these is the management of responsibility, whether in classes, functions, or databases.

GRASP (General Responsibility Assignment Software Patterns) is a set of principles that programmers use to make code that is “responsible”.

In the previous article, the first four principles of GRASP were discussed:

  • Information Expert
  • Controller
  • Low Coupling
  • High Cohesion

These four principle, in short, say that code should be written with as little dependencies as possible to reduce the effects of change (low coupling), meaning that classes with similar responsibilities and dependencies should be connected not directly, but through an interface, or otherwise simplified into one class (high cohesion).

Furthermore, system events should be handled through a single class that manages and coordinates the system behavior using the processes available in other classes (controller). Classes that handle processes should be those assigned with the most responsibility (information expert).

The final five principles of GRASP are the following:

  • Creator
  • Indirection
  • Polymorphism
  • Pure Fabrication
  • Protected Variations

As in the previous post, I will be referencing In10se’s article Mastering GRASP Design Principles for Better Software Design.

  1. Creator: This principle states that classes that require objects should be responsible for their creation. This not only simplifies the creation process, but also supports the high cohesion principle in unifying classes with similar responsibilities.
  2. Indirection: For processes that are used by multiple classes, the principle indirection says that an intermediate class should be created from which other classes may reference (i.e. a notifications class from which classes email and SMS reference).
  3. Polymorphism: This pattern is same one stated in the core principles of Object-Oriented programming by which classes with similar attributes and methods are grouped under a super class where similarities can be inherited and modified accordingly.
  4. Pure Fabrication: There may be cases when there are no classes in which a particular function may fit. In this case, to maintain high cohesion, a new and separate class can be created to handle these functions. However, should too many of these exist, that may indicate that responsibility is not being handled optimally.
  5. Protected Variations: Classes should be responsible for handling their processes; but sometimes, especially for classes that deal with modifying sensitive data, the changes should be encapsulated behind a stable interface to increase the overall system’s robustness.

GRASP taught me a lot about how to better design my code. Looking back at the code I’ve written, I can see that my code would definitely benefit from higher cohesion and lower coupling. Many of my classes and functions are dense with responsibilities that would be more clear if separated into their own dedicated classes.

The point of GRASP is to create cleaner code that is secure and easier to manage. I didn’t think much about programming responsibilities before reading in10se’s article, but now I will be sure to implement these patterns into my future code.

Source: https://medium.com/@in10se/mastering-grasp-design-principles-for-better-software-design-a21b5ec29e89

From the blog Stories by Namson Nguyen on Medium by Namson Nguyen and used with permission of the author. All other rights reserved by the author.

The 9 Principles of GRASP | Part 1

GRASP stands for General Responsibility Assignment Software Patterns. It is a set of principles applied to Object Oriented Programming.

There are nine principles or “patterns” which help programmers understand the responsibilities in software design. In10se on Medium writes a detailed summary on each principle in the article, Mastering GRASP Design Principles for Better Software Design.

  1. Information Expert
  2. Creator
  3. Controller
  4. Low Coupling
  5. High Cohesion
  6. Indirection
  7. Polymorphism
  8. Pure Fabrication
  9. Protected Variations

When developing code, programmers need to identify where to assign responsibility in the code. In software design, responsibility refers to two things: behavior (doing) and data (knowing). Different parts of the code have the responsibility or obligation to “do” the thing itself, such as creating an object or modifying the data.

Programmers can also assign responsibility to the data used by the code such as when the data is public or private, or when to relate data objects for reference, or how the data can be used to generate dependent data.

To keep this post within the acceptable length, I will cover the first four principles this week.

  1. Information expert: this principle states that “responsibility should be assigned to the class with the most knowledge or information required to fulfill the responsibility” (In10se).
    For example, a professor object that has access to every student’s homework and test scores should be responsible for calculating each student’s final grade since this object has access to all the necessary data to do it.
  2. Low Coupling: there should be as little dependencies as possible to reduce the effects of changes in the data and code so to keep different systems separate from each other.
    Instead of having one object be dependent on another, it would be better to create a separate interface that connects the two.
  3. High Cohesion: groups that have related responsibilities should be simplified to a single class for better clarity and maintainability. This also means keeping things that have no related responsibilities separate.
  4. Controller: this principle says that all system events should be handled through a single class that manages and coordinates the system behavior. In10se gives the example of a UserController class that is dedicated to handling user-related events like registering and logging in. However, the actual processes are in other classes.

While writing code is certainly difficult, I find designing the code the hardest part. Just as being fluent in a language doesn’t make me an excellent author, so too does knowing a programming language well not necessarily mean that I can write software that is efficient and effective.

Designing software requires a strong understanding of how to assign responsibility in the code. GRASP contains principles that help guide a programmer’s decision making when designing the software structure so to write a program that not only works, but is also secure and maintainable.

Source: https://medium.com/@in10se/mastering-grasp-design-principles-for-better-software-design-a21b5ec29e89

From the blog Stories by Namson Nguyen on Medium by Namson Nguyen and used with permission of the author. All other rights reserved by the author.

How to Effectively Manage Software Licenses

There is no doubt that licenses are incredibly important in a world where knowledge is being shared and compiled on a global scale. However, there is also no doubt that licenses can be incredibly complex. For this reason, organizations have designed systems to manage software licenses that help make the often convoluted licensing world easier to understand and follow.

Michelle’s blog, Software License Management Best Practices, defines software license management as, “The process of tracking, controlling, and optimizing software licenses within an organization” (Michelle). Through such a system, businesses can more easily maintain legal compliance, reducing unnecessary expenses that results from licensing conflicts, thereby maximizing the value of their software investments.

So how can one create an effective software license management system? Well, just as it is true for all solutions to a problem, here requires a clear and defined strategy.

An effective strategy can take on many forms, and it often varies from company to company depending on the specific circumstances. However, the key is that the strategy must be clear. It should outline the purpose and responsibilities for the organization’s license management system, establishing clear license usage policies and guidelines that are communicated to the executives and developers alike.

Another way to effectively manage licenses is to determine the usage of different software throughout the company. This can be done by cataloging and organizing the software inventory, as well as conducting regular software audits to identify and rectify any software uses are in non-compliance. Having an organized inventory will also help companies keep their licenses up to date, which will allow them to avoid temporary access disruptions and any service fees that may occur from mismanagement.

While many of strategies mentioned above can be done manually, it becomes more and more difficult to manage for larger companies that work with dozens of different software associated with different licenses. For this reason, it is recommended that in such cases, companies use software that utilizes license management tools, which can facilitate the license management process. Of course, it is always better to automate, when possible, to decrease the chances of error.

Software license management is a side many software developers would rather ignore, but it is a necessary aspect of software development that cannot be overlooked. Though I have never developed software that required strict licensing, I will be working on my capstone project next semester, which will require a good understanding of software licensing. For this reason, in addition to learning about the different licenses and how they operate, I also decided to research more about how licenses can be effectively managed to better prepare myself for my capstone project and later in the future when I enter the professional software development field.

Source: https://tangent.com/blog/software-license-management-best-practices/

From the blog Stories by Namson Nguyen on Medium by Namson Nguyen and used with permission of the author. All other rights reserved by the author.

The DRY Principle

One of many important programming principles is what is called ‘Don’t Repeat Yourself’ or ‘DRY’.

The DRY principle focuses on reducing the number of unnecessary repetitions in code. This goal can be achieved through multiple methods detailed in Tahmeed Tarek’s article Understanding the DRY Principle — the three most common being:

  1. Abstraction
  2. Automation
  3. Normalization

Abstraction is often used in Object-Oriented Programming. The strategy is to create a super-class containing the necessary attributes and methods which each class can then inherit. This reduces the number of times common attributes and methods have to be defined.

Automation focuses on communication within the team and between teams working on a project. Cross-functionality between team members and different teams is vital as it gives everyone an opportunity to discuss mutual problems and thereby capable of formulating a mutual solution.

Normalization is often used in designing databases to prevent the occurrence of redundant data. It works by “extracting duplicates into a separate entity” (Tarek), ensuring that the data is consistent and properly distributed so the data’s integrity is maintained at a single source and the database is flexible and scalable.

In addition to the three methods, there are some important things to keep in mind to practice the DRY principle.

The first is to design code that is easy to reuse. This includes elements of clean code such as abstraction and documentation. Code that is simple and easy to read and understand is also easier to reuse. Sometimes, however, this process can be long and tedious, which bring up the next point to keep in mind.

The second is that shortcuts make for long delays. While they may save time in the present, shortcuts introduce what is called ‘technical debt’ which causes problems later in the future. Failing to discover and resolve technical debt early on can be a costly mistake for a project.

The third is to focus on active communication and project awareness. I have personal experience with this point relating to my research project. While still a learning intern, I found myself focusing in on the singular task assigned to me and failing to see the project in its wider scope. This became a problem because I did not think to write my code in a reusable manner for later steps in the project, creating areas of unnecessary redundancy that led to an accumulation of technical debt.

While not a seriously costly mistake — thanks to my advisor — I still had to go back and redesign my code to remove the redundancies. From then on, I learned to apply the DRY principle to my code to prevent the same scenario from happening again.

As I learned from my personal experience, the DRY method is an important principle that guides programmers to develop code that reusable and scalable, making life a lot easier.

Source: https://www.plutora.com/blog/understanding-the-dry-dont-repeat-yourself-principle

From the blog Stories by Namson Nguyen on Medium by Namson Nguyen and used with permission of the author. All other rights reserved by the author.

Writing Clean Code

As many programmers know, running code does not exactly mean good code. In addition to being executable, code also needs to be what is called “clean”, referring to code that is easy to read and understand.

In the article, How to Write Clean Code, Germán Cocca gives explains a large scope of what makes code clean. I have selected three areas that I found most beneficial to me as a CS student:

  1. Format and Syntax
  2. Conciseness and Clarity
  3. Documentation

Firstly, Format and syntax refer to how code is organized. Good format and syntax includes proper indentation, spacing, and variable naming that is consistent throughout the code. Furthermore, it is also important to make sure that variable names are meaningful so that its purpose is clear to the reader.

Secondly, It is good to be clear, but it is also important to keep it concise. Code that is too concise become difficult to understand because it sacrifices too many important details to minimize length. Code that is too detailed however becomes convoluted. Having clear and concise code makes it not only easier to read, but also easier to reuse, and so it is up to the programmer to know when to make the tradeoff between clarity and conciseness.

Thirdly, documentation cannot be understated. There is only so much information that can be expressed through the executable code itself, which is why clean code will always have comments that help guide the reader through what each part of the code is doing. That being said, it is important not to abuse the utilization of comments as this may affect the conciseness of the code. Therefore, comments should be used deliberately and formatted consistently.

Writing code requires a lot of planning and refining. Code will inevitably have to change and improve to meeting new requirements. Having clean code helps make this process more smooth and effective.

I learned this the hard way during my summer internship while using Jupyter Notebooks. Notebooks were especially useful because I was able to execute snip-bits of the code using its multi-cell functionality. However, this put me into a bad habit of not always using meaningful variable names or properly document what I was doing. And worst of all, I would often modify the notebook in ways that blurred the purpose of my code making it difficult to reuse later on.

After being set back a number of times, I realized my mistake and started fixing the way I would write my code. I started utilizing markdown and meaningful variables and would never delete or modify any of the finalized code I wrote, but instead make a new notebook or Python file with a new version noting why the new version was needed.

Poorly writing code may still compile, but it becomes very difficult to maintain. Writing clean code requires practice and awareness, but it is essential to making code easy to read and reusable.

Source: https://www.freecodecamp.org/news/how-to-write-clean-code/

From the blog Stories by Namson Nguyen on Medium by Namson Nguyen and used with permission of the author. All other rights reserved by the author.