Author Archives: Namson Nguyen

The Basics of Security Testing

Security testing is a very important aspect of software development aimed at verifying that software systems are free from design or configuration flaws that could compromise a software’s security. It involves evaluating systems throughout the software development lifecycle to ensure that services and information remain available to authorized users and protected from unauthorized access or tampering.

The main goals of security testing include identifying digital assets, classifying security vulnerabilities, assessing potential consequences of exploitation, reporting findings for remediation, and providing recommendations for addressing vulnerability. Basically, the primary goal of security testing is to determine the security status of an information system.

Security testing ensures that a software complies with security standards, which enhances software quality, and promotes user trust. Continuous security testing is essential because of the constant evolving threat landscape and the potentially devastating costs of cyberattacks.

When data is not securely protected, it’s vulnerabilities can be exploited resulting in data breaches. A case study involving Marriott International shows the significance of security testing in safeguarding such sensitive data to preventing costly security breaches. Marriott experienced two major data breaches in 2014 and 2020, exposing the personal information of millions of guests. Furthermore, statistics show that the average cost of data breaches reached a record of 4.45M in 2023. Such a financial blow could result in the end of many companies (Chavarria).

The key principles of security testing include comprehensiveness, realistic tests, continuity, and collaboration between development, operations, and security teams. This means that security testing needs to be logical, but also applied in a practical enough manner that can be adapted and used by multiple different operations in the program system.

To conduct security testing effectively, the security of a software should be a planned activity in every software development project. Developers should be proactive in addressing vulnerabilities and implement solutions as soon as possible. Automated testing should be integrated into continuous integration and delivery pipelines to ensure that all code complies with security policies.

Security testing is something that I have not learned much about, but this was a good introduction to why it is important and the principles by which it is implemented. In the world of business and competition, good code is not just clean, effective, and efficient code, but it must also be secure code. As I start to work more with things that deal with logins and user information, I will need to pay more attention to how my code is keeping this data secure, so not to have the data be vulnerable to data breaches.

Overall, security testing is important for identifying and mitigating security risks throughout the software development process, which ultimately enhances the security of software systems and protects valuable digital assets.

Source: Security Testing Fundamentals by Jason Chavarria

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.

Dig Deeper

“Dig Deeper” highlights the importance of acquiring in-depth knowledge of tools, technologies, and techniques in software development that help software developers to tackle complex problems effectively. Many software developers get trapped in a stagnant growth pattern and are content with a shallow understanding of their field.

The problem with this mindset is that a shallow understanding often results in challenges when faced with complex issues or unexpected bugs. This shallow understanding also often leads to frustration and hinders the ability of developers to provide meaningful contributions to their projects.

The solution then is to invest time and effort in acquiring a deeper understanding of the tools and technologies used in software development. Rather than merely skimming the surface, developers are encouraged to understand concepts such as concurrency models, type theory, and network protocols which equips individuals with the knowledge to tackle a wide range of challenges and contribute meaningfully to projects.

Moreover, deep knowledge of the field enables developers to explain complex systems, debug effectively, and make informed decisions about technology selection and implementation. This depth of knowledge enables developers to navigate complex problems with confidence and make informed decisions.

It is also important to research information from primary sources, such as specifications and original research papers, rather than relying on secondary or paraphrased sources. By learning more about the original context of ideas and understanding the problems they were designed to solve, developers gain a deeper understanding and can apply their knowledge more effectively.

In addition to looking at the source, software developers are encouraged to engage in activities that deepen their understanding of key concepts and technologies. This may involve implementing solutions from scratch, critically evaluating existing frameworks or libraries, or even keeping a record of their learning journey. By documenting their learning journey through blog posts or other means, developers can reflect on their progress and share insights with others.

As an undergraduate learning to become a software developer in school, I certainly sometimes a mindset more focused on “passing” rather than “succeeding”. I find myself often learning only just enough to earn that “A” instead of really diving deep into the material being taught. This mindset may get me past my academic career, but it will not get me far in my professional career. I will definitely need to devote more time studying about the deeper side of Computer Science, especially the subjects that I feel weaker in, such as Networking and Frontend work.

In summary, the pattern “Dig Deeper” motivates developers to have a deeper knowledge in software development. By investing time and effort in understanding the underlying principles and design considerations, developers can enhance their problem-solving abilities, contribute meaningfully to projects, and ultimately, lead them closer to perfection in their craft.

From Chapter Six, “Dig Deeper” in Apprenticeship Patterns by Dave Hoover and Adewale Oshineye

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.

Record What You Learn

The Apprenticeship Pattern “Record What You Learn” emphasizes the importance of documenting the journey and lessons that a software developer has learned to enhance personal and professional growth. This pattern addresses the common issue that many developers share of repeatedly encountering similar tasks or problems without retaining valuable insights. By maintaining a record of experiences in a journal, personal wiki, or blog, individuals can create a chronological account of the lessons they’ve learned, serving as both inspiration and a valuable resource.

Recording the solutions made to problems encountered along the software journey involves actively documenting experiences, insights, and solutions encountered. The primary problem of not documenting lessons learned is that it causes a lack of learning from past experiences, leading to repetition and inefficiency. Without a record of lessons learned, individuals may find themselves continuously getting slowed down by the same challenges without making much progress.

Maintaining a record of experiences offers several benefits. Firstly, it enables individuals to mentor others by making their journey explicit, sharing insights, and providing guidance based on past learnings. Additionally, it makes it easier to reflect, allowing individuals to identify patterns, make connections, and discover new insights.

To avoid falling into the trap of forgetting valuable lessons, individuals are encouraged to regularly revisit and review their records. By engaging in this process, they can prevent stagnation, identify areas for improvement, and continue evolving. Moreover, have access to and using both internal and external feedback allows the developer to receive more accurate self-assessment which motivates continuous learning and growth.

There are several examples in Apprenticeship Patterns that illustrate how individuals can implement this pattern in practice. For example, maintaining two instances of the same wiki — one for private thoughts and the other for shared lessons — allows for effective self-reflection. Similarly, transcribing ideas that shaped one’s learning into a text file allows it to be kept as a valuable resource for future reference and inspiration.

I believe that recording one’s learning progress it super important to any skill. So often I find myself making the same mistakes over and over again, but then I remember to look at my notes and the past resources I’ve logged for myself, and I find them super helpful in guiding my work to be more efficient and effective.

In conclusion, “Record What You Learn” encourages proactive documentation of experiences and insights to help developers apply what they’ve learned to everyday problems they may face. By methodically recording and reflecting on the lessons learned, programmers can discover valuable insights, avoid repeating past mistakes, and progress on their journey towards mastery.

From Chapter Five, “Record What You Learn” in Apprenticeship Patterns by Dave Hoover and Adewale Oshineye

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.

Sprint 3 Retrospective Blog

With new experience gained from both Spring 1 and Sprint 2, Sprint 3 began without delay as I and my team worked to finish up all our loose ends before the coming end of the semester.

As a team, we all worked very well together in all stages of the final sprint. There was good communication through Discord and SMS to coordinate meeting times both in person and online, through which we collaborated to find solutions to the backlog issues. We were able to effectively work this way, evident through the team’s ability to complete eighteen out of the twenty-one weight we planned at the beginning of the Sprint. Some of the loose ends we needed to wrap were: 1) to get the frontend working, 2) to implement the buttons, 3) to update the Add Inventory Frontend documentation.

Because of the limited time we had, the team was not able to start implementing the new Add Inventory Frontend wireframe design which had been added in Sprint 2. However, we were able to get the frontend to run which we based off the code from Guest Info Frontend. This fix included adding a developer mode which allows for changes made in the code to be automatically updated to the frontend without needing to stop and restart. In addition, my team implemented the original button design and updated the documentation to reflect the new frontend features listed above.

My team and I decided that because there was not enough time to implement the Add Inventory Frontend wirefram design, it would be best to let the next Capstone class pick up where we left off. Firstly, the current layout is not the one represented by the wireframe. This would need to be updated. Secondly, the already created buttons would need to be linked to the backend using the appropriate endpoint call. Both of these are already issues in the backlog and can be used by the next team.

Seeing this sprint and the semester coming to an end, I feel accomplished with the work my team and I were able to get done. I personally learned a lot about the GitLab working environment, linters and how to use them through pipelines, designing frontend frameworks through Vue and HTML, and most importantly, meeting with a team to plan the backlog, collaborating to solve our issues, reviewing code solutions, and presenting our work to the professor at the end of each Sprint and to the entire class at the end of the semester.

Overall, this Capstone class was a growing experience through which I increased my ability to adapt to unfamiliar situations and became more comfortable with taking the initiative at certain times, especially when I was Scrum Master in the first Sprint. I am happy with the progress I and my team were able to make together this Sprint and throughout the entire semester.

Activity links:

Fix Frontend Build: https://gitlab.com/LibreFoodPantry/client-solutions/theas-pantry/inventorysystem/addinventoryfrontend/-/issues/49
Description: Redesigned how Add Inventory Frontend is build, implementing the developer build allowing for live change updates.

Update Frontend Wireframe: https://gitlab.com/LibreFoodPantry/client-solutions/theas-pantry/documentation/-/issues/12
Description: Updated the frontend wireframe in Add Inventory Frontend which had not been merged in Sprint 2.

Update Documentation: https://gitlab.com/LibreFoodPantry/client-solutions/theas-pantry/inventorysystem/addinventoryfrontend/-/issues/46
Description: Updated the Documentation in Add Inventory Frontend to reflect the new features added in all three Sprints.

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.

Static Testing

Static testing is a type of software testing performed during the early stages of the software development lifecycle, which plays a crucial role in identifying defects before they escalate, thereby contributing to the overall security and quality of the software solutions. Static testing involves the examination of software artifacts such as documentation for requirements, test data, unit test cases, and prototypes to uncover errors and structural defects without executing the code.

By identifying and rectifying bugs and errors at an early stage, static testing helps reduce the time and cost associated with dynamic testing performed later in the development cycle. Additionally, static testing aids in minimizing the number of defects that may arise in subsequent stages of development, contributing to smoother and more efficient software delivery.

Static testing encompasses various techniques, including the review process and static analysis. The review process involves informal reviews, walkthroughs, peer reviews, and inspections, each aimed at detecting and resolving errors in different stages of the software development lifecycle. On the other hand, static analysis involves techniques such as data flow analysis, control flow analysis, and cyclomatic complexity analysis, which assess the code’s structure and behavior to identify potential issues.

To facilitate static testing, various tools are available, including Checkstyle, SourceMeter, and ESLint, which assist testers in analyzing code quality and detecting errors. Despite its numerous advantages, static testing also has its challenges, such as the requirement for extensive documentation, compatibility issues with certain programming languages, and the need for frequent meetings and evaluations.

To ensure successful static testing, organizations should provide proper training to testing team members, plan and track testing activities diligently, focus on critical aspects, avoid delays in test execution, and maintain a formal approach to the testing process.

In my coding experience, I am most familiar with dynamic testing, where I work with a well-developed piece of code to ensure that it runs as expected. However, I suppose I do also have some experience with static testing. For example, in my Capstone class, I have worked with linters in pipelines to ensure that committed code passes certain development requires before it can be merged into the main branch. Linters automate a significant portion of the static testing process for developers. However, it is true that not all linters are universally compatible and may only be available for certain languages.

In conclusion, static testing is a vital component of the software development lifecycle, enabling organizations to detect and address defects early, thereby enhancing software quality, security, and overall success.

Source: “What is Static Testing : What you Need to Know!” by Itesh Sharma

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.

Practice, Practice, Practice

Mastery in any skill requires a love for practice and continuous improvement. Practice and improvement can be done through deliberate practice sessions which involves structured exercises tailored to hone specific skills.

One such form of exercise is code katas, inspired by martial arts but applied to software development, which emphasizes the importance of practice, fluidity, speed, and control. Coding katas are short programming exercises where developers solve specific problems or implement algorithms within a set time frame, typically ranging from a few minutes to an hour. Participants work individually or in small groups to write clean, efficient, and maintainable code. The goal is to encourage deliberate practice, enhance problem-solving skills, and promote continuous learning in software development.

Coder’s dojos, provide a supportive environment for practicing code katas in a group setting. These sessions, which are free from stress and interruptions, are crucial for skill development. Short feedback loops ensure that participants receive timely input to avoid developing bad habits.

Practicing different exercises helps discover nuances in skills and prevents stagnation. It’s essential to choose challenging exercises from fundamental computer science books to keep practice sessions interesting and educational. Some recommended books from Hoover and Oshineye, the author of Apprenticeship Patterns is “Programming Pearls” and “Etudes for Programmers.”

It’s often personally difficult to motivate myself to practice coding, though the idea itself is very logically sound. In my spare time, I like to learn new languages like Japanese or Chinese, and these languages, like any language, require lots of focus and practice. Programming is like a language applied to problem solving, so it too requires focus and practice. I should add coding katas to my routine to ensure that I don’t grow rusty on certain areas of my coding knowledge and instead, am constantly growing as a software developer.

In short, taking action is crucial. A software developer needs to find or devise challenging exercises, solve them weekly, observe their progress, and adapt accordingly. This iterative process helps identify strengths and weaknesses, enabling targeted improvement. By embracing practice and seeking constant growth, such as through coding katas, individuals can advance their skills and strive towards mastery in software craftsmanship.

From Chapter Five, “Practice, Practice, Practice” in Apprenticeship Patterns by Dave Hoover and Adewale Oshineye

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.

Find Mentors

Finding mentors is essential for aspiring software craftsmen, as they provide guidance and support in navigating the complexities of the field. Of course, software developers should strive to be hard-working and growing apprentices to eventually become masters at their craft. However, finding an ideal mentor is rare, especially in today’s world.

The process of finding mentors can be challenging, as mentors may not always be readily available or possess the desired expertise. For this reason, most real-world apprentices often seek guidance from multiple mentors with varying degrees of expertise.

Additionally, reaching out and asking for mentorship can be intimidating. However, the potential benefits far outweigh the risks, and even informal advice from experienced developers can be invaluable. Apprentices also have a role to play in mentorship by being willing to share knowledge and provide guidance to others. Passing on lessons learned from mentors contributes to personal growth and development as a craftsman.

Lastly, it is crucial that apprentices be active in approaching mentors, to learn more about them and gain their attention and help. For example, apprentices can sign up for active mailing lists related to software development, they can observe, and identify patient teachers within the community, and seek informal advice from potential mentors at conferences.

As an introvert, I often find myself struggling to take action in the networking aspect of my career, even though I realize how important it is for my success. There is a lot of fear and anxiety that comes with putting yourself out in the open and asking for help. However, if I learned one thing from my internship last summer, it is that I cannot afford to be afraid to ask questions! By asking questions and showing my weakness, yet still in a spirit of curiosity and willingness to learn, I found myself growing faster than I could have ever imagined under the mentorship of my advisor, who was patient and helped me to improve little by little.

In conclusion, mentors play a vital role in shaping the development of aspiring software craftsmen. Actively seeking mentorship and being open to providing mentorship to others are essential components of the journey toward mastery of one’s craft. By embracing mentorship, apprentices can gain valuable insights, overcome challenges, and ultimately achieve their goals in the field of software development.

From Chapter Four, “Find Mentors” in Apprenticeship Patterns by Dave Hoover and Adewale Oshineye

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.

Sustainable Motivations

Programming is automatically motivating for programmers when they have the freedom to work in their preferred manner. However, apprentices often face real-world challenges with projects that have changing demands. Such projects can be rigorous, chaotic, and frustrating, making it essential for programmers to have a constant motivation to adapt and remain resilient. While there are some days where everything flows smoothly, there are also more common days that are filled with complex and tedious tasks, particularly in money-driven programming jobs.

Motivations for programmers can vary, including financial goals, the sheer enjoyment of programming, or building a reputation through open source projects. However, relying solely on financial or reputational motivations can lead to what’s known as the “Golden Lock” phenomenon. This trap involves sticking with known skills because they’re lucrative, even if they no longer align with personal growth or interests. To combat this, an ambition for constant improvement towards mastery is vital, helping developers realize when they’re falling into these traps and guiding them to seek new challenges.

While passion for programming is valuable, it can also lead to overcommitment. For example, Marten Gustafson found himself overcommitting to projects due to his passion, resulting in project “death marches.” It’s essential to nurture this passion while maintaining a balance with other life aspects to avoid burnout.

David Wood offers a simple yet enlightening piece of advice: “Do what you love and the money will follow.” Following this advice helps developers discover that doing what they love fuels their creativity and energy, leading to greater financial rewards in the long run.

To better understand personal motivations, it is encouraged that programmers list at least fifteen motivations and then another five. This exercise helps identify motivations based on personal feelings versus external factors caused by other’s judgment and perception. By prioritizing the top five motivations and keeping them visible during challenging times, programmers can stay focused and resilient on their journey.

On a personal level, I find programming very entertaining and fascinating. But as a student, I often find that my motivation for programming can become fueled by academic reputation. One motivation could be, for example, a fear of getting a bad grade and not making the Dean’s list. While this is certainly a real feeling and truly motivates me to meet the expectations of my professors, it stops at that. Such a motivation is not to become a great programmer, but rather, to become successful in school and therefore in my career. While this way of thinking will probably get me through university, it does not guarantee me a successful career.

Programming offers intrinsic motivation, but navigating the challenges of real-world projects requires adaptive motivations. It’s crucial to balance financial goals with personal interests and ambitions for mastery. By avoiding the Golden Lock, embracing learning opportunities, and nurturing passion while maintaining balance, programmers can find long-term success and fulfillment in their careers.

From Chapter Three, “Walking the Long Road” in Apprenticeship Patterns by Dave Hoover and Adewale Oshineye

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.

Sprint 2 Retrospective Blog

With new experience gained form Spring 1, I entered into Sprint 2 starting strong with more understanding of the basic workflow and how to navigate Thea’s Pantry on GitLab.

As a team, we all worked very well together in all stages of the sprint. There was good communication through Discord and SMS to coordinate meeting times both in person and online which shows by our ability to complete twenty-three out of the twenty-four weight we planned for the start of the semester. Because we were more used to the workflow process, we were able to spend more time together figuring out our more in-depth issues to implement button functionality to the AddInventoryFrontend project.

Some issues we ran into however, was not being able to build and run the Frontend to see how our vue file code ran. Instead, we had to rely on a vue playground which we found online to test and run our code. In addition, we were unable to access the wireframe to edit it, so the team resorted to detailing the revised wireframe through PowerPoint Presentation. These were simple issues that can be fixed in the next Sprint. As expected, we did not repeat any of the workflow mistake we had done last Sprint.

For the next sprint, we plan to have a “Workflow tips” shared document that includes all our mistakes from Sprint 1 and their solutions so that we do not make the same mistake again. For example, instead of waiting to review everything at the end, the team will review issues as they are completed. We also know to create merge requests directly from the issue, and to edit the merge request properly so that it meets all workflow requirements.

For the next sprint, we plan to continue working on the AddInventoryFrontend project. The first step before implementing the revised button wireframe would be to fix the frontend so that it can run on GitPod rather than having to rely on Docker. Then we will add code to allow the frontend to run on devmode, which makes it so that updates pass through as we work on the code rather than requiring the frontend to be rebuilt each time a change is made. After both of these are completed, then we plan to confirm that the current vue code works. Once that is confirmed and running, we will then update the frontend to reflect the revised wireframe.

This Sprint, I was not the SCRUM master, but I attended all our meetings and worked with my team to come up with solutions to our issues. I would say I am much more organized than last Sprint and am happy with the progress I and my team were able to make together.

Activity links:

GitPod Dev Environments: https://gitlab.com/LibreFoodPantry/client-solutions/theas-pantry/inventorysystem/documentation/-/issues/9
Description: Verified that all Thea’s Pantry projects have the correct extensions, linters, and pipeline stages.

AddInventoryFrontend Redesign: https://gitlab.com/LibreFoodPantry/client-solutions/theas-pantry/inventorysystem/addinventoryfrontend/-/issues/39
Description: Created a revised wireframe for AddInventoryFrontend. The revised wireframe will be added to Thea’s Pantry GitLab in Sprint 3.

Implement Frontend Wireframe: https://gitlab.com/LibreFoodPantry/client-solutions/theas-pantry/inventorysystem/addinventoryfrontend/-/issues/45
Description: Developed the submit and cancel buttons following the basic wireframe before revision.

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.

Integration Testing

Integration testing is a critical aspect of the software development cycle, ensuring that individual software components work together cohesively to form a functioning system. It focuses on testing the interactions between modules to confirm that they function as intended when combined into a single system. This makes it easier to identify and address errors that may arise during the integration of multiple components.

Various types of integration testing methods exist, each offering its own advantages depending on the project’s complexity and requirements. These methods include Big Bang, Top-Down, Bottom-Up, Incremental, Sandwich, and Hybrid approaches.

Big Bang Integration Testing involves combining all modules and testing the software system in its entirety. While this method is straightforward, debugging can be complex if issues arise during testing. Although it is simple, this approach allows for quality assurance teams to evaluate the entire system at once, saving both time and effort.

Top-Down Integration Testing prioritizes higher-level modules for evaluation, followed by detailed assessments of lower-level components. This method is effective for thoroughly examining the entire system and breaking it down into smaller parts to identify any inconsistencies.

Bottom-Up Integration Testing begins with critical lower-level modules and gradually works up to higher-level ones. This approach is the reverse of top-down testing and is suited for projects where bottom components are more important top ones.

Incremental Integration Testing involves integrating modules one by one and verifying that each module performs as expected. This testing strategy is effective for detecting problems early in development and ensures that issues are addressed before advancing to further stages.

Sandwich Integration Testing combines top-down and bottom-up integration methods to provide a comprehensive overview of functionality. This approach is suitable for projects requiring both an initial top-down overview and verification that each lower module serves its purpose.

Hybrid Integration Testing combines various integration testing techniques. This method allows developers to choose multiple tests to ensure the system’s flawless operation, depending on the project’s goals and requirements.

Implementation of integration testing involves several steps:

1. Define the scope, identifying test scenarios

2. Prepare test data

3. Create test cases

4. Set up the test environment

5. Execute test cases

6. Monitor and analyze test results

7. Report and track issues

8. Retest and verify

9. Sign off and release the application.

There are many strategies to integration testing. I am curious to try the Big Bang strategy to test my code on a holistic level. While it is simple, it is also thorough, which I think is a perfect strategy to begin with when practicing integration testing.

As a short recap, integration testing ensures that all modules perform according to set criteria. Through integration testing, software developers can confidently roll out solutions and ensure seamless performance when deployed.

References:

The Complete Guide to Integration Testing by Marquel Ellis

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.