My E-Portfolio

Secure Software Development

This module focused on the security risks associated with programming, future trends in secure software development and software architecture.

Teamwork Evidence

As teamwork evidence, we have recorded the videos of our team meetings that can be found below.

Unit 1: Introduction to Secure Software Development

In this first unit we were introduced to the core concepts at the heart of Secure Software Development. With a particular focus on outlining different approaches, their strenghts and weaknesses in relation to software development and architecture.

The main goal of this unit was to understand and familiarise ourselves with the industry standards and best practices which are utilised in the workplace.

The Initial discussion post can be found below:

View Activity Discussion

Unit 2: UML Modelling to Support Secure System Planning

In this unit, the focus was on the use of UML diagrams to support the planning of a secure system. We gained hands-on experience with creating UML models and understood how they can be used to better the communication amongst team members. I look forward to using this knowledge in my team projects at work.

Unit 3: Programming Languages: History, Concepts & Design

In this unit, we explored the history of programming languages, from Alan Turing's work to early languages like Cobol and Fortran, which shaped modern design. We then put theory into practice with Python, learning key concepts like inheritance and polymorphism. The module also covered crucial security best practices to defend against common vulnerabilities. Finally, we learned about design patterns as templates for solving recurring software challenges. We got an overview connecting programming theory with practical, secure coding skills.

This was an interesting yet busy unit, I particularly enjoyed the historical aspect of it.

Unit 4: Exploring Programming Language Concepts

In this module we focused on regular expressions and recursion. Specifically on their security implications, learning not just how to use them, but also the security risks they can introduce. The goal is to understand the pros and cons of each approach, as an aid to writing more secure and effective code.

Additionally, we completed an activity collateral to the reading of Weidman, A. (no date) Regular expression Denial of Service which can be found below:

A regular expression becomes an "Evil Regex" when vulnerable to Regular Expression Denial of Service (ReDoS), an algorithmic complexity attack. This vulnerability arises from "catastrophic backtracking," where the regex engine's evaluation time scales exponentially with input length, consuming excessive CPU resources and rendering systems unresponsive, as famously occurred with Stack Overflow in 2016. The root cause often lies in complex patterns like nested quantifiers (e.g., `(a+)+`) or polynomial overlapping adjacency. Such regexes are notoriously difficult to debug and maintain, and their security risks are often overlooked. The increasing use of AI-powered assistants, which can generate insecure expressions, further exacerbates this problem, as developers may inadvertently integrate vulnerable code. Effective mitigation involves a multi-pronged strategy: transitioning to ReDoS-safe engines like Google's `re2`, employing detection tools, validating input length, and implementing execution timeouts. Although indispensable for security tasks like input validation and sanitisation, the inherent complexity of regular expressions makes them a double-edged sword, frequently introducing denial-of-service vulnerabilities. Consequently, continuous developer education on secure coding practices and rigorous testing of all regex patterns, especially those generated by AI, are paramount to building resilient software.

Unit 5: An Introduction to Testing

In this unit, our focus was on software testing, with a special emphasis on security. We learned essential terminology, various testing techniques, and important industry standards like OWASP. The main goal was to understand how to design effective test plans that could identify and prevent security breaches. We explored practical Python tools to automate testing, including using linters.

Equivalence Testing in Python:

This script demonstrates a concept called equivalence partitioning, which is a way of sorting a collection of items into groups based on a specific rule. The rule for this example states that two numbers, x and y, are considered equivalent if the difference between them is divisible by 4. This is checked with the code (x - y) % 4 == 0. The script applies this rule to a set of integers from -3 to 4, and then checking if each is divisible by 4. The result is the creation of four distinct groups where all numbers in a group are equivalent to each other under that rule. For instance, the numbers 1 and -3 are placed in the same group because their difference is 4, which is divisible by 4. The output first lists the groups ({0, 4}, {1, -3}, {2, -2}, {3, -1}) and then shows how each individual number from the original set maps into one of these groups.

Unit 6: Using Linters to Support Python Testing

In this module, our focus was on using Python technologies to develop high-quality and secure code. We delved into linters, learning how to apply different ones, appreciating their unique contributions and how to use them in various scenarios. The main objective being providing us with the tools to develop Python code so that it would be free from error and designed consistently.

I found the linterst to be a particularly interesting topic, as it is something which I have been using and I feel that I now grasp much better.

In this module, we also submitted our first assignment which consisted of a Design Document prepared by our team, and a peer review.

Unit 7: Introduction to Operating Systems

In this unit, our focus was on Operating Systems and their relationship with programming and security. We learned the core functions of a typical OS, looking at common examples and the key differences between processes, threads, and schedulers. We also discussed crucial approaches for enhancing OS security and compared various virtualisation methods. A significant part of the week was understanding the distinction between dynamic and shared libraries, recognising the security implications they have when our applications need to interact with the operating system.

What is an Ontology?:

The software development lifecycle incorporates critical testing phases to ensure system integrity. For a complex application like an e-commerce platform, integration testing is essential, verifying the interoperability of components such as the product catalogue, shopping cart, and payment gateway. This phase confirms seamless data flow and interaction, utilising test doubles like mocks and stubs to create controlled environments. Mocks can simulate external payment services, enabling rigorous testing of transaction logic without real financial processing, while stubs can provide predefined responses from an inventory system that is not yet complete. Following successful integration, system testing evaluates the entire e-shop as a cohesive whole. This holistic assessment validates end-to-end functional workflows, from user registration to order fulfillment, and assesses non-functional requirements such as performance under high user loads and security against potential threats. The final stage, acceptance testing, ensures the platform meets business objectives and user expectations. User Acceptance Testing (UAT) involves target users performing real-world scenarios to validate usability and functionality, often through beta testing. Concurrently, Operational Acceptance Testing (OAT) confirms the e-shop's operational readiness, scrutinising procedures for deployment, backup, and recovery. A similar multi-layered testing strategy is fundamental to delivering a robust, reliable, and secure e-commerce experience.

Unit 8: Cryptography and Its Use in Operating Systems

In this unit, our focus was on cryptography, exploring its principles, technology, and use with operating systems. We examined the meaning of cryptography and its application through a case study involving OS integration. A significant part of our learning was dedicated to exploring common cryptographic libraries and building a basic application that used these libraries to encode sample data.

Below, the link to the discussion centered around TrueCrypt can be found:

View Activity Discussion

Unit 9: Developing an API for a Distributed Environment

For this module, our focus was on practical Python development skills crucial for our summative assessment. We built an API and used it to create and read records, which involved investigating CRUD capabilities and expanding our knowledge of Python libraries. We also reflected on the utility of an ontology in a distributed architecture. The key outcome was creating an API for file management, a significant step that involved bridging our secure back-end code with a user interface, expanding our skills from server-side development to include UI interaction.

Unit 10: From Distributed Computing to Microarchitectures

In this unit, our focus was on system architectures, from monolithic deployments to microservices and virtualisation. We explored their evolution, strengths, and weaknesses, with a strong emphasis on security. We learned how distributed systems increase the attack surface and examined security attacks specific to virtual environments. A key takeaway was the importance of encryption and key distribution to protect data in modern, distributed applications. This brought the module into a timely and relevant context of distributed operations.

Faceted Data:

The concept of "faceted data" provides a robust, language-based methodology for enforcing information flow security to prevent data leakage. As introduced by Schmitz et al. (2016), this paradigm centres on "faceted values"—data constructs that dynamically adapt their behaviour and representation based on the privilege level of the observing context. This mechanism ensures sensitive information is only exposed to authorised entities, offering a strong confidentiality guarantee that is independent of application-level bugs. The primary strength of this model is its ability to enforce security at a fundamental level, decoupling information flow from application logic. However, the paradigm presents considerable implementation challenges, particularly when translating it from functional languages like Haskell, which use sophisticated constructs such as control and data monads. In object-oriented languages like Python, simulating this behaviour would conceptually require wrapper classes and context managers to track observer privileges, introducing significant architectural overhead and potential performance impacts. While a direct translation is complex, the core idea of context-aware data representation remains a powerful strategy for building secure systems, though its practical adoption requires navigating a steep conceptual curve and substantial engineering effort.

Unit 11: Future Trends in Secure Software Development

Furthermore, we submitted our second assignment which consisted in an indipendently developed CLI Python application. The design document previously submitted as its starting point.

Below, the link to the debate on Microservices and Microkernels can be found:

View Activity Discussion

Unit 12: The Great Tanenbaum-Torvalds Debate Revisited

For the last unit, our focus was on the historic Tanenbaum-Torvalds debate. We revisited their 1990s arguments over monolithic versus microkernel operating systems, considering them in both their original context and today's security-conscious world. We analysed how modern trends like microservices and constant cyber-attacks influence these design choices. This debate prompted us to critically re-evaluate our opinions on monolithic versus modular system architectures, thinking about which approach is best suited for the challenges of today's distributed and security-focused computing landscape.

Additionally, we submitted our third assignment, which consisted in the completion ofthis e-portfolio.

Object Oriented Programming

This module focused on the principles of object-oriented programming in Python. We learned about classes, inheritance, polymorphism, and encapsulation. The module also covered data structures and algorithms, including their implementation in Python. UML diagrams were used to model the design of the programs.

Reflection on Object-Oriented Programming

This reflection utilises the Four F's (Facts, Feelings, Findings, Future) framework to critically evaluate the learning experience of Object-Oriented Programming (OOP) concepts. As a junior frontend engineer primarily experienced with JavaScript and having only brief prior exposure to Python, this module, grounded in Allen B. Downey's "Think Python" and involving a project on designing robot-human interaction, offered a structured immersion into OOP principles such as Encapsulation, Abstraction, Inheritance and Polymorphism: interacting objects on which the structure of OOP programs is based, promoting modularity, reusability, and easier maintenance by breaking down complexity into manageable, encapsulated parts.

Facts

The module systematically introduced fundamental OOP concepts using Python. Key topics such as class definition, object instantiation, attributes, and methods were all put to the test through the system design of initial implementation of a project aimed at supporting robot-human interaction. For the project of a warehouse robot, the system architecture was designed using OOP principles involving classes such as WarehouseRobot, PackingSystem, StockSystem, and others - each containing specific variables - managing their states and interactions effectively.

The project exhibits dynamic behaviour through interactions, Unified Modelling Language (UML) provides Interaction Diagrams specifically to visualise and analyse them.These diagrams are crucial for understanding system behaviour, debugging interactions, validating designs against requirements, and communicating the dynamic flow that a system like the Warehouse Robot uses.

To ensure a system behaves as expected we employ techniques such as debugging (finding and fixing errors), error handling (managing runtime issues) and testing (systematic verification of the software functioning as expected). These techniques are critical for creating reliable software and therefore foundational to professional software development.

Feelings

Engaging deeply with Python's approach to OOP felt like exploring familiar territory (object concepts) through a new lens. Having primarily worked with JavaScript objects, prototypes, and ES6 classes in a frontend context, Python's structure felt notably explicit and, in some ways, more formally defined.

Python's connections to JavaScript were evident. Python's class syntax offered a conceptual parallel to JavaScript's ES6 class, although the underlying difference between Python's class-based inheritance and JavaScript's prototypal inheritance was an important difference. The explicit nature of Python's self was different to the more context-dependent behaviour of JavaScript's this keyword. Python's clear separation of mutable (list) and immutable (tuple) sequence types also provided a different perspective compared to JavaScript arrays. Both languages clearly support multiple paradigms, including object-oriented and functional approaches.

The required self parameter, while initially feeling unnecessary compared to JavaScript's implicit this, quickly became appreciated for its clarity, removing the ambiguity often encountered with this binding in JavaScript callbacks or different execution contexts.

While comfortable manipulating objects and using classes in JavaScript for UI components or state management, the formal OOP structure presented in "Think Python" felt more rigorous, although there was an appreciation for Python's syntactic clarity. Concepts like class-based inheritance felt more straightforward compared to navigating JavaScript's prototype chain, especially having only briefly encountered Python before. Designing the robot-human interaction project using these principles was challenging but ultimately rewarding, as the OOP structure helped organise the complexity. Debugging interactions, however, sometimes felt frustrating, echoing similar challenges in complex JavaScript applications but perhaps highlighting Python's stricter error handling (e.g., TypeErrors).

Findings

The most significant finding was a reinforced understanding of OOP's power in managing complexity for building robust, maintainable software – a principle highly relevant to frontend architecture, demonstrated clearly through the robot-human interaction project. The module provided an excellent, accessible pathway into these structured concepts. Python's emphasis on explicit self and its relatively stricter typing encourages a discipline that can be beneficially applied back to frontend software development, promoting more predictable state management and interaction logic. While JavaScript offers immense flexibility (often needed for dynamic UIs), Python's more structured approach to OOP provided a solid conceptual foundation that might be less explicitly taught in typical frontend onboarding. Learning formal OOP through Python provided a valuable framework to critically assess JavaScript practices. It encouraged moving beyond simply using objects or basic classes towards intentionally designing with OOP principles like encapsulation and clear inheritance/composition patterns, even within a primarily JavaScript role.

Learning formal OOP through Python provided a valuable framework to critically assess JavaScript practices. It encouraged moving beyond simply using objects or basic classes towards intentionally designing with OOP principles like encapsulation and clear inheritance/composition patterns, even within a primarily JavaScript role.

Future

The structured understanding of OOP gained from this module will directly influence my professional approach as I intend to apply principles of clear encapsulation, well-defined interfaces, and thoughtful use of classes (or functional alternatives where appropriate) when building JavaScript components and managing application state, aiming for greater modularity and testability. Understanding Python's explicit self reinforces the need for careful testing and management of this in JavaScript.

This experience motivates exploring formal design patterns (Strategy, Observer, etc.) more deeply and applying them within frontend frameworks. The principles practiced in the robot-human interaction project – designing clear class hierarchies and managing object interactions – are directly applicable to designing complex UI components and state management logic. This cross-language perspective, rooted in a solid OOP foundation gained via Python, enhances my ability to architect robust and maintainable applications, contributing positively to my professional growth.

Unit 1: An Introduction to Python Programming and the OO Programming Paradigm

For this unit I have setup a basic Python environment to understand the basics of the Object-Oriented Programming Paradigm. I have accessed the Think Python textbook for the first time and found it to be a great resource for understanding the basics.

Unit 2: Object Oriented Analysis - Initial Steps towards Programming in Python

In Unit 2 we went deeper into the Object-Oriented Programming Paradigm using Chapter 16 and 17 of the Think Python textbook. Chapter 16 covers defining your own data types using classes (like a Time type) and looks at functions that either change objects or create new ones. Chapter 17 then transforms these functions into methods directly associated with the class, introduces special methods for setup (__init__) and display (__str__), and explains how operators like + can work with your custom types.

Unit 3: Unified Modelling Language (UML)

In this Unit we learned about UML diagrams and how they provide value throughout the Software Development Life Cycle. The ways in which they are used are as follows: Use Case and Activity diagrams dominate early requirements analysis to capture functionality and workflows; Component, Package, and Deployment diagrams shape high-level architectural design; detailed design heavily relies on Class, Sequence, Communication, and State Machine diagrams to specify object structure and interactions; these detailed diagrams then serve as a reference during implementation and inform test case design alongside Use Case and Activity diagrams for validation. All diagrams collectively act as crucial documentation for ongoing maintenance.

Unit 4: Applying a UML Model to a Program Implementation: UML in Practice

In this Unit we studied the implementation of UML diagrams in more depth, and we started working on the first submission for this module. An example of a class diagram is shown below:

Class Diagram

Unit 5: More on Classes

For this Unit we focused on Classes, examining in depth the concepts of modularity, inheritance, aggregation, and composition. In addition, the concept of polymorphism was further explored through a practical excercise that can be found below:

polymorphism-exercise

Unit 6: Abstract Methods and Interfaces

For this Unit we focused on the concept of Abstract Methods and Interfaces and how they can be used to create more flexible and reusable code.

Unit 7: Debugging / Error Handling, Data Structures and Data Search

In this Unit we gained an understanding of how fundamental debugging code and handling errors are, and how to do so with the tools provided by Python. Furthermore, we continued to look at data structures to familiarise ourselves with different structures and apply a range of tecniques to them.

The activity Discuss the ways in which data structures support object-oriented development. Use examples of three different data structures to contextualise your response. can be found below:

Object-Oriented Programming (OOP) in Python relies fundamentally on built-in data structures to effectively manage the state encapsulated within objects and the relationships between them. While classes define the blueprint, structures like list, dict, and set provide the practical mechanisms for organising data internally. For instance, the list, an ordered and mutable sequence, is commonly utilised within an object to manage collections where sequence or multiplicity is important. A ShoppingCart object, for example, naturally employs a list to store Item objects, preserving the order of addition and allowing duplicates, thereby directly implementing the "has-many" aggregation or composition relationship central to many object-oriented designs. The list's inherent methods for appending, inserting, or accessing elements by index become integral parts of the encapsulating object's behavior.

Beyond simple ordered sequences, dictionaries (dict) and sets (set) offer specialised capabilities crucial for other common OOP scenarios. The dict, storing key-value pairs, enables highly efficient data retrieval based on unique identifiers, making it ideal for managing associations or internal mappings within an object, such as a UserRegistry using usernames as keys to quickly access User objects. Conversely, the set provides an unordered collection of unique elements, perfectly suited for situations where only the presence and uniqueness of items matter, like managing unique tags associated with an Article object, inherently preventing duplicates. Thus, list, dict, and set are not merely containers but essential tools integrated within object design, enabling the practical realisation of encapsulation, association, and efficient state management vital to robust object-oriented systems in Python.

Unit 8: Data Structures and Data Search in Practice

In this Unit we experimented with data stractures and practical operations on them. We also practiced the ways algorithms can be implemented using Python.

The Collaborative Discussion can be found below:

View Activity Discussion

Unit 9: Packaging and Testing

For this Unit we learned about testing and how to implement tests in a Python program. Through the textbook Review of Automated Test Case Generation, Optimisation, and Prioritisation Using UML Diagrams: Trends, Limitations, and Future Directions by Kongarana, S. R., Rao, A. A. and Raju, P. R. (2024), we learned how leveraging UML diagrams can help in having a structured approach for the automated generation of test cases. Their work surveys how models such as sequence or state diagrams can be systematically analysed to create test suites, optimise them for better coverage or reduced redundancy, and prioritise test execution. It also explores the limitations of this approach, like the focus on only certain diagram types and the need for better handling of model complexity.

The exercise on Cyclomatic Complexity can be found below:

cyclomatic-complexity-exercise

Unit 10: Testing Code in Practice

In this Unit we learned how to write tests for a Python program and how to use tools like pylint to check the quality of the code. From the reading we learned that building quality software requires verification through testing to ensure it works correctly and meets requirements, and that this focus on quality means creating reliable and standard-compliant applications.

Unit 11: Pointers, References, Memory, and Design Patterns

In this Unit we learned about pointers, references, memory, and design patterns. This unit also included the submission for the implementation of the system we designed for the assignment in Unit 7.

The System Implementation assignment can be found below:

View System Implementation Assignment

Unit 12: Working with Design Patterns to Structure Code

In the final unit we learned about design patterns and how they can be used to structure code. For example, The Factory design pattern simplifies object creation by centralising the instantiation logic, allowing software to produce objects without knowing the specific class beforehand. Multiple design patterns are often used together within a single software project, and certain patterns frequently complement each other and are thus commonly applied in combination.

In this unit the e-portfolio was worked on and the final submission was made.