NOROFF UNIVERSITY COLLEGE
November, December 2020
1. WEEK 1 – INTRODUCTION TO OOP
MOODLE URL : https://lms.noroff.no/blog/index.php?entryid=43486
1.1 Reflection on the days lecture and tutorial
However my experience in object orientation remains minimal as most of my job is written in a functional style, so I really hope to gain a lot from the time we have here. It’s clear from my general reading that it’s arguable majority popularity makes it essential knowledge for the future. Johan stated that it’s unlikely a data scientist would architect a system from scratch, yet it’s probably a paradigm you will have to work in.
Some initial conversations with a studio teammate and a colleague from work both agree and refute this viewpoint with the main response angle that object orientation gives the programmer great power in a large system but this comes with great responsibility! The non-deterministic behaviour makes things difficult to predict further down the line and it’s hard to keep a track of original instantiations.
Counter to this negativity, it must also be true that there are major benefits to be found otherwise it’s popularity wouldn’t be so great. The ability to create abstractions seems primary to me. To mention it’s origins briefly before reflecting on this week’s lectures, it’s worth noting that it was the brainchild of Alan Kay a highly respected and renowned computer scientist. He made an analogy to biology (link):
- ’First, cells conform to basic “master” behaviors.
- Second, cells are autonomous and they communicate with each other by sending messages.
- Third, cells become different parts of the organism, depending upon the context’.
With this abstract overview of the paradigms goals, what follows is attempted introspection into some of the first week’s topics.
This week served as a timely refresher on terminology and conventions. When you stop and think about it the implications are clear but it’s easy to be a little vague as a novice when for example using the phrase instance attribute.
Controlling the scope of different attributes is vital to avoiding the aforementioned side effects. Use of the superclass as done last year comes to mind.
1.1.3 Getters, setters and property
These enable a layer of abstraction and encapsulation to the underlying working methods inside a class as well as the opportunity for forcing validation methods. I hadn’t really used property before so it was valuable to understand how that forces usage of the getters and setters. The banking example as mentioned provides an obvious need for secure validation and privacy when dealing with sensitive information.
1.1.4 Access modifiers
One underscore equals protected status whilst a double underscore equals private but it’s important to note that Python allows access unlike other languages if you already know of their existence and namespace.
1.1.5 Multiple inheritance
The ordering of input parameters is vital to know in the context of multiple class inheritance. This style is advised against as it can be hard to trace the processes if you didn’t author the code!
1.1.6 Overloading the operator
Special keywords enable the use of the operator on objects, for example __or__ enables use of the ‘|’ operator. This article (link) was helpful for me in understanding some of the potential consequences of doing this. The syntax of double underscores is key to ensure ‘private’ status allows a function to allow arguments of different types for different situations. The method should be a member of a class and this will “reduce the number of arguments by one”.
1.1.7 Method signatures
The advantages of docstrings include helping “you understand the capabilities of a module or a function.” (link). At work I’ve been told by experienced devs that it is just so hard to remember the underlying features of your code and that leaving a trail of logic is just essential. Docstrings make this task easier as you can return the text from the docstring as you work for example using help().
Finally, the lecture style of naturally talking and discussing the code on screen is by far the best format for me personally. I find myself much more engaged and learning more than the simple repetition of a slide deck. Coding live provides so much more opportunity for very helpful and descriptive comments whether it be terminology or a typical error. Next week, Johan has promised us a contrast to this introductory week as we dive into the finer points of OOP – I’m looking forward to it!
2. WEEK 2 – DESIGN PATTERNS
The completion of week two allows me to further reflect on the effectiveness of object oriented programming against some initial concerns (from background reading, linked to in week one’s journal). In short I now feel that in light of a very valid argument from Johan, any criticism of the most popular paradigm of coding appears to be a little idealistic from the perspective of a second year student. Johan’s angle was that most libraries are written in this style (such as the sklearn example) and so when your future job is likely to revolve around manipulating these, it pays to be very comfortable with the form.
2.2 THE STRATEGY PATTERN
The strategy pattern plays a major role in the paradigm of OOP and so it was great to dive into that this week. It is considered a behavioral pattern with numerous other patterns coming under the structural or creational style. Succinctly put, this pattern enables different strategies to be swapped in and out without any side effects.
A popular use case is the selection of different algorithms as demonstrated in the image below. This enables selection at run-time and so a much more dynamic setup is possible. Equally there is an element of future proofing as any number of other algorithms or strategies can be swapped in or out.
Reducing redundancy or duplicate code is one of the main benefits of object orientation and this is also possible in the strategy pattern as it is likely many strategies have some commonality. By extracting “the varying behavior into a separate class hierarchy” (Refactoring Guru) the DRY principle can be followed.
An interesting aspect of this pattern is the possibility to “isolate the business logic of a class from the implementation details” (Refactoring Guru) which enables further reusability and a better separation of concerns.
Image 1 – the strategy pattern (link)
This pattern requires usage of an interface that contains abstract classes with which we used the builtin “abc” library as shown below in code I wrote for the tutorial with a payment processing use case.
Image 2 – abstract class example from my notebook
The interface entails three distinct levels of abstraction:
- Define the interface – firstly abstract class, secondly method classes
- Define usage of the interface – instantiate and create class(es) that allows request of selection of method strategy
- Create usage of the interface – use super() and select strategy as a parameter
The reason for this process was explained in the lecture (image 3 below) and acted as an introduction to topics we will soon tackle in more detail with particular focus on late binding. The independent ‘decision class’ will decide on the appropriate strategy and this is referred to as the ‘context’ of the pattern.
Image 3 – why should we use an interface or abstract class (from class slide)
One important element covered was the need for concrete strategies, not just instantations. This article (link) helped clear up my inability to clearly define the difference the terminology implied. In short it enables the above use of polymorphic substitution and the ability to instantiate sub-classes. This is a principle known as favouring composition over inheritance.
Image 4 – background reading
Image 4 shows an informative excerpt from a book I’m finally getting value from! It was good to learn that Python’s first class function approach enables cleaner syntax.
In addition I was able to read Martin Fowler’s (well known for his book Refactoring) article on patterns (link) and hope to expand on some of the points in following reflective journals such as how to select the right pattern and how granular one needs to be.
2.3 THE OBSERVER PATTERN
This pattern was introduced to us at the end of the week without too much time to fully explore it and I intend to reflect more on it next week. In short though I’m really looking forward to writing more code in this style as it’s a personal goal to become more fluent with the set of features it entails. Most code I’ve written outside of Noroff involves parsing or cleaning data followed by some selection logic. The observer pattern however is much more related to ‘state’ and functionality seen in api design for example. The aforementioned book I’m currently reading highlights the main pattern value of separation and detachment between the code that’s doing the observing and the code that’s being observed.
All in all it’s been a positive week and very motivating to be working on the fundamentals of our future careers. It’s challenging to be not quite fluent in the terminology yet but I see an improvement in the number of times I have to look something up! The lecture style is clear, concise and well paced, particularly with the opportunity to code along in real time
3. WEEK 3
3.1 OBSERVER PATTERN CONTINUED – DAY 9
Test the above classes and reflect on ways in which these could be useful in your own designs.
The task of handling dynamic rather than static data in applications is an obvious example for this pattern. To be able to ‘react’ to a user input such as a form or present different options based on parameters such as location are pertinent to my current job and perhaps our upcoming assessment. Certainly it’s a pattern we are discussing in our studio group as it will be a graphical interface which the user interacts with to retrieve certain information. A further piece of terminology which has become a lot clearer is the definition of event driven apps, where the subject is usually called a “stream of events”.
An apparent commonality with a lot of these well established patterns is that there is some overhead, some cost to ‘setting up’ the design with all the abstract classes and instantiations. However with this pattern the payoff is clear – a complex chain of actions can be fulfilled in a reactive sense. I look forward to seeing this in action with some of my code in the future.
What would be the strengths or weaknesses of this approach?
The observer pattern can be said to be highly extensible, enabling robust and flexible code to be authored as stated by Johan in the lecture and cited as the primary benefit by a colleague at work. His preference for it is one of the reasons we employ the Model View Control architecture. For example the ‘observers’ can be selected at run-time as the relationship with the ‘subjects’ is known as ‘loosely coupled’ since they have ‘no explicit knowledge of each other’.
A virtue of many of the patterns is that they enable composition over inheritance but here we have only inheritance due to the need for concrete observers. This also makes it easy to end up with an overly complex pattern. A further negative aspect of the pattern is that it can cause memory leaks, known as the lapsed listener problem, because it requires both explicit registration and explicit deregistration.
3.2 DECORATOR PATTERN – DAY 10
Today was an introduction to the decorator pattern (not to be confused with the decorator in Python, denoted with a @ symbol above a function). This pattern has been the most intuitive for me thus far with a high level concept of layering and wrapping classes. It really protects the ‘internal’ and original code which stops unintended side effects yet allows for easy extensibility (via type matching).
Johan mentioned the chain-like delegation through the layers somewhat resembles recursion whilst highlighting the need to monitor the overall complexity of the design. As with others this pattern very much future proofs the design and enables flexible usage via dynamic runtime behaviour.
My current book (OOP by Dusty Philips) highlights the pattern in p316, mentioning it’s popularity and exploring alternative solutions such as monkey-patching. Two very clear points from the lecture for me were that this pattern doesn’t require use of the super() initialisation (abstract base class usage means the compiler is able to assume a connection – its not deep enough to require explicit definition) and that un-wrapping is not possible.
Image 5 – example of bloat in an decorator pattern (from Refactoring.guru)
3.3 DAY 11 – STRATEGY PATTERN REVIEW
Today was nothing new per se, rather a review of the strategy task from last week where we were to swap stack and queue algorithm strategies. I definitely appreciate the opportunity to repeat and re-engage with information in this way. So often it feels like one is just trying to ‘keep up’ and get to grips with the essentials without being able to achieve any sense of mastery by completing a task simply. I wouldn’t personally claim that today but after another thorough walkthrough from Johan I feel much better placed in grasping the logic of the separate pieces of object orientation.
Repetition of the principles this week has definitely helped me build my internal mental model and justified the reasoning for a new way of writing code. Discord has been a valuable resource this year – a dedicated ADS server has led to more lecture discussion. Of note for me was Johans use of the error handling in the advanced function method. In principle this is standard practice but something I have yet to adopt as a default in my code, something I really want to be doing by the end of this course. Interested to see what the factory pattern holds in store for tomorrow.
3.4 DAY 12 – THE FACTORY PATTERN PART 1
My first interaction with the ‘factory’ terminology was during the summer whilst reading a JS book (Composing Software) from Eric Elliot. It’s intuitive that this pattern is part of a larger system, the word having the clear connotation of producing something. Yet for me I’ve struggled a little in being able to 100% define the process – where am I just manipulating data versus creating new objects. This lecture definitely took my understanding a step further despite being inexperienced with regards to having authored examples.
As stated in the lecture the main benefits are the ability to remove instantiations and the encapsulation of business logic into one class so that there is only one place where code will be edited. Further background reading also indicated how common it can be for this pattern to be used in conjunction with the observer pattern which makes sense therefore enabling that pattern to in turn be simpler and more robust with less instantiation and more encapsulation.
A key point (highlighted below in image 6) is that the encapsulation happens because the subclasses decide what objects to create. Having had a sneak peak at the remaining lecture slides for part two I’m particularly keen to understand ‘inversion’ in more practical detail.
Image 6 – a key point for me in the lecture slides
Image 7 – current coffee factory progress
4. WEEK 4
4.1 DAY 13 – THE FACTORY PATTERN PART 2
Getting further into this pattern after our initial introduction was valuable. For me it took some time to really decipher the key points of the lecture, to really distill down all the new terminology and implications of design choices. I won’t of course claim to grasp the advanced elements after so little time coding this way but I feel I’ve advanced my knowledge somewhat.
Today’s lecture had some notable points. To reiterate, the factory pattern gets passed as a parameter and it carries out the instantiation making it more robust to future change. Johan mentioned his preference for always coding out a basic factory pattern first and to avoid attempting a complex solution that perhaps involves multiple factories.
This makes sense as it necessitates you to work through the problem slightly more linearly. I know I’ve made the mistake of assuming I have a clear implementation in my head and ending up with errors and disorganised, messy code by skipping the base case scenario.
The Abstract factory method is suitable when variants are needed. As stated on the Refactoring Guru site, “subclasses may return different types of products only if these products have a common base class or interface”. So one can say it’s clearly a creational design pattern but with a narrow focus on concrete implementations with commonality.
A major benefit I had not quite grasped at first is that it’s possible to dispense of complex if/elif/else conditional structures. I found a great example on Real Python’s site which made it very clear. It’s something I’ve struggled with in my own code and so the recommendation is to “look for a common interface that can be used to replace each of the paths”. This of course assumes a scenario where there isn’t a large number of paths but has the positive side effect of making the code easier to read as the paths available are so clearly defined.
4.2 DAY 14 – THE FACTORY PATTERN PART 3
Johan mentioned early in the lecture that the upcoming information makes use of the hooking concept which is general programming terminology for extending the functionality of software. This is achieved by avoiding any coding of a specific instantiation and instead using abstraction as we inherit the superclass. Furthermore, inheritance of the desired subclass is achieved by a selector type initialisation as shown in the class example below. This appears to me a rather clean, easily readable way to create the correct ‘side effects’ and enable ‘plug and play’ behaviour to be achieved with maximal efficiency.
Image 8 – defining desired inheritance
I found the concept of ‘inversion’ particularly interesting and something I hope to employ in my own code. Essentially we invert the typical tendency to think and visualise the flow of code from top to bottom, that is from the highest level of abstraction and downwards. By planning and writing our code iteratively from an inverted perspective we can achieve minimal dependencies in our system and achieve robustness. This way both high and low level components depend on abstraction rather than instantiations.
Image 9 – dependencies
Image 9 from the slides above, helped my understanding in the same way that it really helped to draw UML diagrams in first year database design. In this way you can visually check to avoid variables holding references to concrete classes and maintain loose coupling.
A final insightful topic of the lecture regarded employing multiple interfaces and factories to take care of various parts of a design. Johan stated if you find yourself rewriting code too often then this style can help ensure better encapsulation despite it appearing initially a little convoluted.
Writing the code for the tutorials was very worthwhile. As always it’s the small details that catch me out and what initially appears as replication instead forces you to see the problem you are trying to solve rather than think only of the high level concepts. After this the benefits and reasoning summarised from the lectures above are clearly realised. I will admit to still feeling a touch nervous and curious about this implementation in a larger programme or codebase!
4.3 DAY 15 – THE FACTORY PATTERN – ALTERNATIVE EXAMPLE
4.3.1 The fog of learning
Again, a very useful lecture. I notice that personally, there is always a certain amount of time that it takes to lose the foggy uncertainty whilst grappling with a new topic. Awkward and unintuitive are common words when it comes to learning in general.
That’s why I appreciate the utility of a walkthrough lecture like this. It really creates time to soak up the principles where repetition or usage of a different context is helpful. I know when I’m making satisfactory progress when I start to predict the upcoming point or code that will be made. If I’m constantly surprised by each sentence and find myself pressing pause and rewind too often, I know I have a long way to go!
4.3.2 Complexity and consistency
To reflect specifically today, I feel I am halfway towards feeling satisfied. I feel like the terminology is becoming a lot more intuitive and I can visualize the higher abstracted patterns clearer. It was interesting to note that Johan considers the abstract factory pattern the most complex pattern which seems very true as it is comprised of mixing multiple patterns.
The internal consistency provided by the pattern was a substantial point in the lecture. Essentially there is value in grouping similar products so that the abstract factory can help tune the exact inheritance process but maintain internal consistency and functionality. Configuration of an object is perhaps descriptive in this sense. With regards to pattern choice, it was good to know that what appears a touch convoluted at first is actually highly suitable to a situation where the requirements will continue to grow in the future.
As seen below in image 10, I was able to extend the program functionality without editing existing classes – I simply added new classes for the ork’s. Because of the design, decorator usage and inheritance this was quick to do. To provide a variety of weapons for a goblin soldier I added a method inside the instantiation of the weapon, with random assignment inside of the GoblinEquipmentFactory.
Image 10 – ork generator
4.4 DAY 16 – WRAPPER PATTERNS – ADAPTER AND FACADE
The practical benefits of the adapter pattern were much more immediately tangible to me than others thus far. Working with API’s seems to be an integral part of data science and thus I expect to be writing a lot of adaptor functionality in the future. The adaptor is a type of wrapper but rather than extending functionality it maps to other methods providing a conforming interface.
As well as handling incoming data streams via an API, another middleware type function this pattern can enable is backwards compatibility. As Johan pointed out libraries are always changing and so it’s key to be able to handle changes in your dependencies. There is a limit though to how much this pattern should be implemented in a single project before there is more utility in a complete rewrite.
Stack Abuse makes a similar argument to Johan that we should prefer to use object adapters rather than at class level so as to prevent unintended side effects through multiple inheritance. Also of note that adaptors can’t solve every situation – the outputs must be somewhat similar for it to make sense.
4.4.2 The facade pattern
Perhaps the simplest pattern yet, the key outcome is that of a unified interface with the enablement of decoupling dependencies – ideal with regards to the principle of ‘least knowledge’. The data dashboard discussion really struck a chord with me as something I find at my job happens a lot! What looks so simple externally has involved so much work behind the scenes! Over use of facade type wrappers can hurt runtime performance also, something we learnt in our algorithms classes – a small change can soon make a massive difference when it comes to dealing with big data.
My solution for the problem posed would be to replace the instantiation of Spear() with a call to the adaptor which inherits Spear() behaviour. In that method is a conditional based upon location which will provide the correct weapon to all goblins.
5. WEEK 5
5.1 DAY 17 – SINGLETON PATTERN
Despite frequently reading about the evils of global variables, I never really investigated the ‘why’, more than understanding the potential invisible side effects it can result in across a project. This class was useful in deeper identifying further implications of using a global object when the object is significant, such as taking up system resources.
Essentially today’s pattern overcomes many of these issues and ensures that ultimately there is a single instance of an object in existence. This ‘protection’ of creation and access that the pattern provides is enabled by a private constructor and potential use of the _thread module in Python to prevent multiple thread usage. We can use __new__ rather than __init__ in our Python code to do this as it runs before it and ensures a greater level of control.
Johan stated early on that it was the simplest pattern so far which makes sense as there is little ‘invisible’ or inherited behaviour to mentally comprehend versus the others. It’s purpose is nearly always extension of functionality rather than having hierarchical control. In situations of thread control it takes on a lot of responsibility.
He also hinted at controversy surrounding it’s usage (potentially breaking the single responsibility principle) and engineer Maximiliano Contieri is strong in his criticism in a Hacker Noon blog post stating seventeen arguments against it! A colleague at work was rather nonplussed about it saying he never really uses it. Interestingly Wikipedia links to its origins in mathematics (set theory) which I appreciate a bit more after our discrete module last year.
5.2 DAY 18 – COMBINING PATTERNS
This class is perhaps our most valuable in relation to our upcoming exam as we tackle the combination of various patterns. Our Java codebase at work heavily relies on the model-view-control pattern so it was valuable to learn a little about its definition as a compound pattern.
The compound pattern which strikes me as a real attempt to simplify things within the framework of a tree structure. The lecture then progressed into completing a couple of various versions of the duck simulator. Johans live coding and explanation at each step is always helpful and today he made some interesting comments and reminders for us that seem very agreeable:
- A simple wrapper would be the solution to enable type checking in Python.
- Always use private methods where possible
- The adapter pattern always requires the object to be wrapped as a parameter
- The contract analogy is useful
- Don’t overcomplicate the definitions – think of them as wrappers primarily.
- Most importantly strive to understand the principles rather than copy a structure
The final notable topic for today was a further introduction and demonstration of the static method usage, implemented as ‘@staticmethod’. It doesn’t need initialized and is static by default if positioned in the class structure correctly. I really like Dan Bader’s (Real Python) definition that a “static method can neither modify object state nor class state. Static methods are restricted in what data they can access – and they’re primarily a way to namespace your methods”. They make a real case that the primary advantage is the clear intent and readability of the code it creates.
5.3 DAY 19 – COMBINING PATTERNS CONTINUED
With our flock example in class we were able to find out a bit more about this week’s new pattern, the composite pattern. The image below gives a clear definition of its implementation in which similar processes can be applied to both leafs and containers. Refactoring Guru also echoes Johans mention in the similarity that has to the decorator pattern in having a primary function of extensibility.
Image 11 – composite pattern (Refactoring Guru)
A couple of helpful pointers and reminders were given to highlight the mitigation of common mistakes. Firstly do not overuse the static method as it can easily create memory leaks. Secondly factories can ensure consistent object creation and prevent forgetting to add a decorator for example.
I really liked the way of summarising and demonstrating the way that an abstract factory can so easily create different versions of the same object. The original class was not edited once all the way through the example making clear how extensible object oriented code can become when the right patterns are used. My colleague highlighted that one of his main motivations in writing his code is to make it reusable – he would hate to spend all his time on something that serves no future purpose! He mentioned that yesterday he added a new observer with just three functions and thirty lines of code with reused logic in our complex back-end thanks to the design pattern.
5.4 DAY 20 – MODEL-VIEW-CONTROLLER PATTERN
A short lecture to wrap up the OOP course was given today with some detail on the well known ‘MVC’ compound pattern and some guidance on the assessment.
MVC combines composite, strategy and observer patterns to separate the logic and outputs of a program, what’s referred to as a ‘separation of concerns’. It’s perhaps not vital for us as potential data scientists but would be if we had any aspirations as software developers. At work I’m lucky enough to be able to get familiar with this design and although my responsibilities in the codebase are very narrow I do use one of our numerous controllers to display my work. It was a lot to comprehend at first and I still only feel comfortable in my own basic use cases but I can only imagine how necessary this separation and encapsulation is required at large companies!
Image 12 – the MVC pattern overview (from class slides) which we use at work
Very helpfully, Johan took the time to talk through key parts of the assessment and what level of detail he is really looking for in combination with what good OOP code really achieves and how we can demonstrate that. I’m looking forward to taking that advice into the following days where I really put together the main building blocks of our programme.
6.1 REFERENCES WEEK 1
- Property vs. Getters and Setters in Python – DataCamp. (18/12/2018). Retrieved November 8, 2020, from https://www.datacamp.com/community/tutorials/property-getters-setters
- Operator and Function Overloading in Custom Python Classes – Real Python. (n.d.). Retrieved November 7, 2020, from https://realpython.com/operator-function-overloading/
- (Tutorial) Docstrings in Python – DataCamp. (10/4/20). Retrieved November 8, 2020, from https://www.datacamp.com/community/tutorials/docstrings-python
- If everyone hates it, why is OOP still so widely spread? – Stack Overflow Blog. (2/09/20). Retrieved November 8, 2020, from https://stackoverflow.blog/2020/09/02/if-everyone-hates-it-why-is-oop-still-so-widely-spread/
- What does object-oriented programming do better than functional programming, and why is it the most popular paradigm when everybody seems to say functional programming is superior? – Quora. (12/3/2018). Retrieved November 6, 2020, from https://www.quora.com/What-does-object-oriented-programming-do-better-than-functional-programming-and-why-is-it-the-most-popular-paradigm-when-everybody-seems-to-say-functional-programming-is-superior
- (Alan Kay: Transforming the Computer Into a Communication Medium). (n.d.). Retrieved November 8, 2020, from http://www.it.hiof.no/grit/forelesning/AlanKay/AlanKay.pdf
- Operator Overloading. (2007-08-27.). Retrieved November 7, 2020, from http://faculty.cs.niu.edu/~mcmahon/CS241/c241man/node93.html
6.2 REFERENCES WEEK 2
- Philips, D (2018) Python 3 Object-Oriented Programming. Birmingham, UK: Packt Publishing,
- Abstract Base Classes in Python: Fundamentals for Data Scientists | by Erdem Isbilen | Towards Data Science. (27/6/20). Retrieved November 13, 2020, from https://towardsdatascience.com/abstract-base-classes-in-python-fundamentals-for-data-scientists-3c164803224b
- Strategy Design Pattern. (4/5/09). Retrieved November 10, 2020, from http://www.blackwasp.co.uk/Strategy.aspx
- Strategy. (n.d.). Retrieved November 13, 2020, from https://refactoring.guru/design-patterns/strategy
- Writing Software Patterns. Martin Fowler (1/8/20). Retrieved November 10, 2020, from https://www.martinfowler.com/articles/writingPatterns.html
6.3 REFERENCES WEEK 3
- Observer pattern – Wikipedia. (n.d.). Retrieved November 20, 2020, from https://en.wikipedia.org/wiki/Observer_pattern
- Observer. (n.d.). Retrieved November 19, 2020, from https://refactoring.guru/design-patterns/observer
- Observer Pattern | Object Oriented Design. (n.d.). Retrieved November 21, 2020, from https://www.oodesign.com/observer-pattern.html
- Philips, D (2018) Python 3 Object-Oriented Programming. Birmingham, UK: Packt Publishing
- Decorator. (n.d.). Retrieved November 17, 2020, from https://refactoring.guru/design-patterns/decorator
6.4 REFERENCES WEEK 4
- The Factory Method Pattern and Its Implementation in Python. Isaac Rodriguez. (n.d.) Retrieved November 28, 2020, from https://realpython.com/factory-method-python/
- Factory Method. (n.d.) Retrieved November 28, 2020, from https://refactoring.guru/design-patterns/factory-method
- Structural Design Patterns in Python. Darinka Zobenica (n.d.) Retrieved November 28, 2020, from https://stackabuse.com/structural-design-patterns-in-python/
6.5 REFERENCES WEEK 5
- Singleton (mathematics) – Wikipedia. (n.d.). Retrieved December 1, 2020, from https://en.wikipedia.org/wiki/Singleton_(mathematics)
- Singleton pattern – Wikipedia. (n.d.). Retrieved December 1, 2020, from https://en.wikipedia.org/wiki/Singleton_pattern
- Singleton Pattern: The Root of All Evil | Hacker Noon. (14/7/20). Retrieved December 1, 2020, from https://hackernoon.com/singleton-pattern-the-root-of-all-evil-e4r3up7
- Python’s Instance, Class, and Static Methods Demystified – Real Python. Dan Bader (n.d.). Retrieved December 2, 2020, from https://realpython.com/instance-class-and-static-methods-demystified/
- Design Patterns: Composite in Python. (n.d.). Retrieved December 2, 2020, from https://refactoring.guru/design-patterns/composite/python/example