-
- Objectives
- to review basic principles of component design
- to explain the role of detailed design patterns in software design
- to draw attention to the wide range of available detailed design patterns.
-
Introduction
Figure 1 shows that software design is reached through an iterative process in which a functionality-based architectural design is revised to ensure that it satisfies quality attributes before proceeding to detailed design.
In Chapter 3 a design pattern was presented as an existing design solution to a common problem that captures experience and good practice in a form that can be reused, and we explained that there are a range of pattern types (Ch. 3 Figure 1) with different abstraction scopes and different levels of domain independence. In this chapter we examine detailed design patterns but focus on how an architectural pattern can be realised by detailed patterns which in turn can be realised in code, noting that generic code for many detailed design patterns has already been written and can be sourced from the Internet.
Before elaborating on detailed design patterns it is worth reminding ourselves of the key concepts of good design, which are applicable to architectural design and detailed design. In Chapter 2 we drew attention to four design principles: information hiding, separation of concerns, planning for change and fault tolerance. Figure 2 shows how these principles can be elaborated into key design concepts. Table 1 lists 5 detailed principles of implementing these concepts in object-oriented approaches.
Table 1: S.O.L.I.D Principles of Design [9] (📹 Bob Martin SOLID Principles of Object Oriented and Agile Design) Single responsibility principle: A class should have only a single responsibility (i.e. changes to only one part of the software's specification should be able to affect the specification of the class) Open/closed principle: Software entities should be open for extension, but closed for modification. Liskov substitution principle: Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program. Interface segregation principle: Many client-specific interfaces are better than one general-purpose interface. Dependency inversion principle: One should depend upon abstractions, [not] concretions. -
Architectural Patterns and Detailed Design Patterns
Architectural Patterns represent a broad class of solution to a broad class of problem. Modern day information system problems are complex and hence have complex solutions that typically require more than one architectural pattern. As the detail of a problem is understood, so the detail of the solution is elaborated and architectural designs (using architectural patterns) are developed into more detailed designs (using detailed design patterns) which in turn are implemented in code.
The key to designing with patterns is being able to recognise the similarities between the problem at hand and similar problems that have been addressed before. For example, we should recognise that a driverless car engine management system that we wish to build is similar to weather forecasting systems and traffic flow management systems that have been built in the past, in that they all have to process real-time data streams (“events”). Recognising the similar problem allows us to see that a solution can be grounded in a similar solution i.e. the use of an event-based architectural pattern. Then, after having studied the detail of the problem further, we may recognise that the driverless car system needs to receive different data types from multiple concurrent clients, and that a solution can be grounded in using some combination of event handling detailed design patterns such as a Reactor pattern (🔗 https://dzone.com/articles/understanding-reactor-pattern-thread-based-and-eve ). A Reactor pattern receives messages, requests, and connections coming from multiple concurrent clients and processes these posts sequentially using event handlers thus avoiding the common problem of creating a thread for each message, request, and connection.
In [1] Gamma et al. (1995) (the “Gang of Four” – GoF) adapted the concept of patterns for software development and catalogued 23 detailed design patterns aimed at meeting some commonly-recurring object-oriented design needs at the level objects (component/ subsystem interactions). Simplified explanations of these 23 design patterns are presented in [2]. These 23 patterns were catalogued into Behavioural Patterns, Creational Patterns, and Structural Patterns. The GoF patterns continue to be an important influence on both current and emerging patterns. They are used to make designs more reusable and flexible i.e. more robust to change through adhering to the S.O.L.I.D principles. Many of the GoF patterns have been coded up in a variety of programmes languages [3, 4] . Appendix 1 lists a set of video sources that explain these different patterns.
Since 1995 many other detailed design patterns have been developed and put together in different pattern collections e.g. [5-13]. Some of these patterns are domain independent and can in principle be used for any type of system. Some have been developed for a particular application domain. Many have been developed do something very specific e.g. messaging to support enterprise integration [7]. A disadvantage of using design patterns can be that they are often not well documented or documented using different nomenclature that it can be difficult to understand them in relation to the specific context you are dealing with. For modest size applications they can sometimes also be too complicated and unnecessary.
As a software engineer the professional development challenge is not to set out to memorise all the detail of all these different patterns and the nuances of their different application contexts (that would be impossible and in years to come we may be supported by intelligent software design agents to do this for us) but to take a keen interest in knowing what pattern collections exist and what the theme of each collection is. Then from time to time browse through these collections like you would browse through a book, a journal article or a news report, broadening and deepening your understanding of what problems people have had to solve in the past and the solutions (described as patterns) they have developed to those problems.
Listen to this podcast (Sept 2017) with Linda Rising on design patterns – entitled the Importance of Patterns, Her Journey & Patterns for Driving Change/Innovation
🔊 Linda Rising on the Importance of Patterns, Her Journey & Patterns for Driving Change/InnovationExample: MVC Pattern
In the rest of this section we will illustrate the relationship between an architectural pattern and detailed design patterns using the MVC architectural pattern and some GoF patterns.
- Let us assume that a user is interacting with a windows-based application interface (rather than a command line application interface). One or more different user interactions can take place:
- User can change the data within a window on a screen (there can be multiple windows of course)
- User cannot change the data within a window on a screen
- User can change the display regardless of the data e.g. scrolling, zooming, deleting the window
- User cannot change the display.
- Referring to Figure 3 the user interaction is with a View. We are going to assume that there is a single Controller that determines which of these windows to display and which will be updated depending on what data changes in the model.
- Each View
- sends user actions (e.g. button click, scroll bar click, data entry) to the Controller
- receives notification from the Model that any data relevant to that View has been updated
- receives notification from the Controller to display itself or not
- The Controller
- Receives user interaction from a View
- When a user changes some data in an “editable” View, the Controller for this View passes this data on to the Model and tells the Model to update itself
- The Controller tells a View whether to display itself or not.
- The Model
- represents the data
- receives notifications from the Controller and Other Systems about what data to change
- notifies the relevant Views that data pertinent to that View has changed
In more complex applications the data content of several different windows may also be updated automatically regardless of user input. For example, an investment trading application receiving continuous changes in the share price data of all FTSE-100 companies would update periodically all application windows showing the rolling FTSE-100 average. In these cases the Model would be receiving data from other input sources and the Controller would also need to be notified that the model had been updated by these other sources, so that it would know which Views to display.
1You can also search for “design patterns” in www.github.com
-
Creational Patterns
Creational design patterns focus on the creation of objects, instantiation mechanisms and any constraints on number and type. They can be broadly separated into class creation patterns and object creation patterns. Class creation patterns use inheritance for instantiation. Object creation patterns use delegation. Appendix 1 shows the set of GOF creational patterns.
Example – Factory Method
The Factory is a creational pattern that allows a client process, when it needs to create a concrete object, to do this indirectly using a Factory method rather than doing it directly itself (using say a new operator). This is helpful when a client knows all the possible objects that it might want to create but only finds out during runtime which one it needs to create. Putting all the code in the client for checking which possible object type needs to be created and all the creational code for doing so makes the client overly complex and it will need to change every time any aspect of an individual object types needs to change.Problem Context:Figure 4 shows that a Client tells a FactoryBase object about the type of concrete object it needs. The FactoryBase instantiates a new ConcreteFactory, which creates a new ConcreteProduct of type ProductBase, and then returns the ConcreteProduct to the client.- FactoryBase. This is an abstract base class for the concrete factory classes that will actually generate new objects. An abstract class is normally used so that other standard functionality can be included and inherited by subclasses.
- ConcreteFactory. Inherits from the FactoryBase class, and the concrete factory classes inherit the actual factory method. This is overridden with the object generation code unless already implemented in full in the base class.
- ProductBase. This abstract class is the base class for the types of object that the factory can create. It is also the return type for the factory method. Again, this can be a simple interface if no general functionality is to be inherited by its subclasses.
- ConcreteProduct. Multiple subclasses of the Product class are defined, each containing specific functionality. Objects of these classes are generated by the factory method.
Problem Solution:Figure 5 shows how a Client (RobotArtist) uses a ConcreteFactory object (shapeFactory) of class FactoryBase (ShapeFactory) to create new ConcreteProduct objects (shape1 – circle; shape2 – rectangle; shape3 – square) from the class ProductBase (Shape). For example in a Restaurant system, to create different types of menus, a Restaurant client can use a ConcreteFactory object (menuFactory) of class FactoryBase (MenuFactory) to create new ConcreteProduct objects (menu1 – a la carte menu; shape2 – 2-course menu; shape3 – 3- course menu) from the class ProductBase (Menu) see Figure 5b.Example Problem:✓ avoids binding applications-specific classes into client code
✘ client code may have to subclass the FactoryBase class just to create a particular ConcreteProduct objectConsequences:See 💡 Table 2Implementation:XTable 2: Creating Shapes using a Factory Pattern 1 Create an interface. Shape.java public interface Shape { void draw(); }
2 Create concrete classes implementing the same interface. Rectangle.java public class Rectangle implements Shape { @Override public void draw() { System.out.println("Inside Rectangle::draw() method."); } } Square.java public class Square implements Shape { @Override public void draw() { System.out.println("Inside Square::draw() method."); } } Circle.java public class Circle implements Shape { @Override public void draw() { System.out.println("Inside Circle::draw() method."); } }
3 Create a Factory to generate object of concrete class based on given information.
ShapeFactory.javapublic class ShapeFactory { //use getShape method to get object of type shape public Shape getShape(String shapeType){ if(shapeType == null){ return null; } if(shapeType.equalsIgnoreCase("CIRCLE")){ return new Circle(); } else if(shapeType.equalsIgnoreCase("RECTANGLE")){ return new Rectangle(); } else if(shapeType.equalsIgnoreCase("SQUARE")){ return new Square(); } return null; } }
4 Use the Factory to get object of concrete class by passing an information such as type.
RobotArtist.javapublic class RobotArtist { public static void main(String[] args) { ShapeFactory shapeFactory = new ShapeFactory(); //get an object of Circle and call its draw method. Shape shape1 = shapeFactory.getShape("CIRCLE"); //call draw method of Circle shape1.draw(); //get an object of Rectangle and call its draw method. Shape shape2 = shapeFactory.getShape("RECTANGLE"); //call draw method of Rectangle shape2.draw(); //get an object of Square and call its draw method. Shape shape3 = shapeFactory.getShape("SQUARE"); //call draw method of circle shape3.draw(); } }
5 Verify the output. Inside Circle::draw() method. Inside Rectangle::draw() method. Inside Square::draw() method.
-
Structural Patterns
Structural patterns focus on how classes and objects are organised to form a larger structure. Appendix 1 shows the set of GOF structural patterns.
Example - Composite Pattern
The Composite is a structural pattern because it is used to form large object structures across many disparate objects. It is defined [1] as “allow(ing) you to compose objects into tree structures to represent part-whole hierarchies.”Problem Context:See Figure 6. The Component defines an interface for all objects in the composition: both the Composite and the Leaf nodes. It may implement a default behaviour for add(), remove(), getChild() and its operations. The Composite‘s role is to define the behaviour of the components having children and to store child components. The Leaf defines the behaviour for the elements in the composition. It has no children.Problem Solution:One example of a Composite structure is a restaurant menu system, where a menu has many menu items and each menu item can have submenus. Anything that can be modelled as a tree structure can be considered an example of Composite. Another example is an organisational chart. Within the context of MVC the Composite can be used to store data in the Model and to support its presentation in a View.Example Problem:✓ complex objects can be decomposed into primitive (leaf) objects
✓ primitive objects can be combined and composed into complex objects
✓ clients can treat composite objects and primitive objects uniformly
✓ New kinds of components can be added more easily
✘ By providing such flexibility and transparency, there is a trade-off on the Single Responsibility Practice that should be borne in mind and as it grows it can become overly general and difficult to find objects.Consequences:Consider a Menu Component in which a Menu class becomes a Composite and a MenuItem class becomes a Leaf class. Composites (Menu) and Leafs (MenuItem) implement operations which may not make sense (e.g. implementing add() method in MenuItem class) so in that case an exception might be generated. 💡 Table 3 shows some example code.Implementation:XTable 3: Composite Code Example
# abstract class MenuComponent { // Composites' methods public function add( $menuComponent ) { throw new UnsupportedOperationException(); } public function remove( $menuComponent ) { throw new UnsupportedOperationException(); } public function getChild( $index ) { throw new UnsupportedOperationException(); } // Leaves and composites' methods public function getName() { throw new UnsupportedOperationException(); } public function getDescription() { throw new UnsupportedOperationException(); } public function getPrice() { throw new UnsupportedOperationException(); } public function isVegetarian() { throw new UnsupportedOperationException(); } public function doPrint() { throw new UnsupportedOperationException(); } } # class MenuItem extends MenuComponent { // properties here ($name, $description, $vegetarian, $price) // __construct(), getName(), getDescription(), getPrice() // and isVegetarian() are here... public function getListing() { $result = " " . $this->getName(); if( $this->isVegetarian() ) { $result .= "(v)"; } $result .= ", " . $this->getPrice(); $result .= " -- " . $this->getDescription() . "\n"; return $result; } }
# class Menu extends MenuComponent { // properties here ($menuComponents, $name, $description) // __construct(), getName(), getDescription() are here... public function add( $menuComponent ) { $this->menuComponents[] = $menuComponent; } public function getChild( $index ) { return $this->menuComponents[ $index ]; } public function getListing() { $result = "\n" . $this->getName(); $result .= ", " . $this->getDescription() . "\n"; $result .= "---------------------------------\n"; $iterator = new ArrayIterator( $this->menuComponents ); while( $iterator->valid() ) { $menuComponent = $iterator->current(); $iterator->next(); if( !is_null( $menuComponent ) ) { $result .= $menuComponent->getListing(); } } return $result; } } # class Waitress { private $allMenus; public function __construct( $allMenus ) { if( !$allMenus instanceof MenuComponent ) { throw new InvalidArgumentException(); } $this->allMenus = $allMenus; } public function printMenu() { $menu = $this->allMenus->getListing(); echo $menu; } }
-
Behavioural Patterns
Behavioural patterns describe how objects interact with each other. Appendix 1 shows the set of GoF Behavioural Patterns.
Example 1: Observer Pattern
An Observer Pattern [1] is a solution for describing a 1-to-many dependency between objects so that when one object changes state its dependents are notified. An Observer object notifies a Subject (under observation) object that it wishes to be notified of any change to the Subject object’s’ state.Problem Context:See Figure 7. One or more Observers are interested in the state of a Subject and register their interest with the Subject by attaching themselves. When something changes in a Subject that the Observer may be interested in, a notify message is sent, which calls the update method in each Observer. When an Observer is no longer interested in a Subject's state, they can simply detach themselves.Problem Solution:In the context of an MVC for a restaurant system, the Model contains access to data objects and rules governing food product costs, meal costs and meal prices. The data objects are likely to be may be in the Domain Logic Layer and not SQL tables in the database. There might be a different View for each different menu type e.g. A La Carte, 3-Course Meal. Changes to costs/prices in the Model are reflected in the menus seen in the Views.Example Problem:✓ Subjects and observers can be reused independently
✓ Coupling is between abstract classes (or interfaces): not between concrete classes
✓ Observers are easily changed without changing the subject
✘ If many updates are sent to the Observer simultaneously and Observer sends a corresponding call back to Subject messaging processing bottlenecks can occur
Consequences:💡 See Table 4. Some language frameworks support some patterns directly (see 💡 Appendix 2 Sidebar). For example in the java.util package the work required to define the interface that makes the Observer pattern work is already done. Table 3 shows a code example for the Observer pattern. In a restaurant example, the Screen class could contain a Component Menu (see section Example – Factory Method).Implementation:Example 2 Strategy Pattern
The Strategy pattern is a behavioural pattern that allows a client process when it needs to use an algorithm to do this indirectly using a Strategy interface rather than doing it directly itself. This is helpful when the client knows all the possible algorithms that it might want to use but only finds out during runtime which one it needs to use. The alternative which would be putting all the code in the client for checking which possible algorithm needs to be used and all the calling code for executing it would make the client overly complex and needing to be changed when the algorithm set changed.Problem Context:In Figure 8, the Client class is the user of an interchangeable algorithm. It includes a property to hold one of the strategy classes. This property is set at run-time according to the algorithm that is required. StrategyBase is an abstract class for all classes that provide algorithms. It may be implemented as an interface it provides no real functionality for its subclasses. The concrete strategy classes inherit from the StrategyBase class and each provides a different algorithm to be used by the client.Implementing the Strategy Pattern
Problem Solution:Suppose there is a game in which players run around a circuit that includes a set of checkpoints and at each checkpoint, the player must throw projectiles at a target. Points are scored for successful hits. However there are three different levels of speed for moving around the circuit and the points scored depends on the level selected which itself can be varied during game play. We can create a Scoreboard class that outputs the score for a person playing a game with the score based upon the number of targets hit. The calculation of the score will use one of three sets of rules according to the speed level of circuit travel. The scoring rules are as follows:
Level 1. One hundred points will be awarded for every target hit.
Level 2. Two hundred points will be awarded for every target hit.
Level 3. Three hundred points will be awarded for every target hit.Example Problem:✓ Another way to support alternatives than many conditional statements.
✓ Enables different implementations of the same behaviour.
✓ There is a communication overhead between Client and the Strategy
✘ Increases the number of objects in an application which may be an issue when memory usage is at a premium.Consequences:💡 Table 5 shows the code for the scoreboard and the scoring algorithms. The test code creates a new scoreboard and displays three scores. Each score using a different scoring algorithm.Implementation:XSidebar: MVC Implementation Issues
Forms are enclosed in the HTML form tag. This tag specifies the communication endpoint the data entered into the form should be submitted to, and the method of submitting the data, GET or POST. Forms can be made up of standard graphical user interface elements. Forms are usually combined with programs written in various programming languages to allow developers to create dynamic web sites. The most popular languages include both client-side and/or server-side languages. On the Client-side the de facto client-side scripting language for web sites is JavaScript. Using JavaScript on the Document Object Model (DOM) leads to the method of Dynamic HTML that allows dynamic creation and modification of a web page within the browser. While client-side languages used in conjunction with forms are limited, they often can serve to do pre-validation of the form data and/or to prepare the form data to send to a server-side program. Server-side code can do a vast assortment of tasks to create dynamic web sites — from authenticating a login, to retrieving and storing data in a database, to spell checking, to sending e-mail — quite unlike client-side programs. A significant advantage to server-side over client-side execution is the concentration of functionality onto the server rather than relying on different web browsers to implement various functions in consistent, standardised ways. In addition, processing forms on a server often results in increased security if server-side execution is designed not to trust the data supplied by the client and includes such techniques as HTML sanitisation. Some of the interpreted languages commonly used to design interactive forms in web development are PHP, Python, Ruby, Perl, JSP, Adobe ColdFusion and some of the compiled languages commonly used are Java and C# with ASP.NET.
ASP.NET Web Forms is a part of the ASP.NET web application framework and is included with Visual Studio. It is one of the four programming models you can use to create ASP.NET web applications, the others are ASP.NET MVC, ASP.NET Web Pages, and ASP.NET Single Page Applications. ASP .NET Web Forms are pages that your users request using their browser. These pages can be written using a combination of HTML, client-script, server controls, and server code. When users request a page, it is compiled and executed on the server by the framework, and then the framework generates the HTML markup that the browser can render. An ASP.NET Web Forms page presents information to the user in any browser or client device.
Using Visual Studio, you can create ASP.NET Web Forms. The Visual Studio Integrated Development Environment (IDE) lets you drag and drop server controls to lay out your Web Forms page. You can then easily set properties, methods, and events for controls on the page or for the page itself. These properties, methods, and events are used to define the web page's behaviour, look and feel, and so on. To write server code to handle the logic for the page, you can use a .NET language like Visual Basic or C#.
- The main advantages of ASP.net MVC are:
- Enables the full control over the rendered HTML.
- Provides clean separation of concerns(SoC).
- Enables 🔗 Test Driven Development (TDD).
- Easy integration with JavaScript frameworks.
- Following the design of stateless nature of the web.
- RESTful urls that enables SEO.
- No ViewState and PostBack events.
XTable 4: Observer Code Example
import java.util.Subject; public class DataStore extends Subject { private String data; public String getData() { return data; } public void setData(String data) { this.data = data; //mark the Subject as changed setChanged(); } } public class Screen implements Observer { @Overridepublic void update(Subject o, Object arg) { //act on the update } } Screen screen = new Screen(); DataStore dataStore = new DataStore(); //register observer dataStore.addObserver(screen); //send a notification dataStore.notifyObservers();
XXTable 5: Code for Strategy Example
Scoreboard board = new Scoreboard(); Console.Write("Level1 "); board.Scoring = new Level1ScoringAlgorithm(); board.ShowScore(7); Console.Write("Level2 "); board.Scoring = new Level2ScoringAlgorithm(); board.ShowScore(4); Console.Write("Level3 "); board.Scoring = new Level3ScoringAlgorithm(); board.ShowScore(3); /* OUTPUT */ Level1 700 Level2 800 Level3 900 public class Scoreboard { public ScoringAlgorithmBase Scoring { get; set; } public void ShowScore(int hits) { Console.WriteLine(Scoring.CalculateScore(hits)); } } public abstract class ScoringAlgorithmBase { public abstract int CalculateScore(int hits); } public class Level1ScoringAlgorithm : ScoringAlgorithmBase { public override int CalculateScore(int hits) { return (hits * 100); } } public class Level2ScoringAlgorithm : ScoringAlgorithmBase { public override int CalculateScore(int hits) { return (hits * 200); } } public class Level3ScoringAlgorithm : ScoringAlgorithmBase { public override int CalculateScore(int hits) { return (hits * 300); } }
-
Implementing the MVC Example
The user manipulates a View and an event is generated. Events cause a Controller to change a Model, or View, or both. Whenever a Controller changes a Model’s data or properties, all dependent Views are automatically updated. Similarly, whenever a Controller changes a View, for example, by revealing areas that were previously hidden, the View gets data from the Model to refresh itself.
Figure 9 shows one way of implementing a Model-View-Controller pattern using the detailed design patterns Factory, Composite, Observer and Strategy. The actual choice of detailed design patterns will depend on the application for which the MVC is being used. Here, the Model plays the role of Subject while the View is the base class for Observers. The Model may contain a range of different data types and structures and be constructed using a Composite class. Typically, there are different Views. A Factory method can be used to create each View. A View itself might be complex. For example, a View that was a control panel of buttons may be implemented as a set of button views. Then, the Control Panel View may be created as a Composite pattern of Button Views. A Strategy pattern may be used to present different calculations in the same View or different Views. There are different schools of thought about the relationship between the number of Controllers and the number of Views. They can be 1-to-1 or a Controller can control more than one View. The choice will depend on the normal criteria about complexity of the application, likely changes that will occur, performance impact. A general rule of thumb is to keep Controllers small in complexity creating more if necessary.
Over the years the MVC itself has been replaced by other variations e.g. Model-View-Presenter and Model View ViewModel.
-
Implementation Issues
The selection of implementation technologies can often affect some of the architectural and detailed decisions. The most common example of this is when a popular architectural framework is deployed to support the development of some aspects of the proposed system e.g. Eclipse, .NET, Javabeans, CORBA. The decision to deploy one or more frameworks is often a good one e.g. to reduce time and cost by reusing existing software, to maintain a level of known quality, to integrate with an existing system that has used the framework. A cautionary note is that frameworks often come with few flexible components i.e. it’s all or nothing, and hence three possible architectural mismatch problems can arise:
i. the framework provides all those aspects of desired functionality it is intended for it to provide, but also provides some elements that are not desired
ii. the framework provides all those aspects of desired functionality it is intended for it to provide, but in a way that causes a problem with another aspect of the design
iii. the framework provides some but not all aspects of desired functionality that is intended to provide.- When any of these situations arise several options are possible:
- Change the architectural style to fit the framework
- Develop glue code to support the framework in meeting all the aspects of the architectural design
- Ignore the unneeded parts of the framework
- Put a wrapper around the framework to permit access to only the needed parts of the framework.
The decision to use the framework is a judgement against each option’s benefits, costs and risks, and is made by the software architect after a discussion with the design team and often as part of the architectural analysis (Chapter 5).
📖 The portfolio of techniques, tools, platforms, frameworks, languages are regularly changing and keeping up to date as software professional development is demanding. So it is good to know a few places where to look and understand where the market is. One source, free, is at 🔗 https://www.thoughtworks.com/radar. Others, not free, are Gartner (🔗 www.gartner.com) and Forrester (🔗 www.forrester.com), two large reputable consultancy firms that produce robust surveys and analysis However buying these survey reports can cost £2000-3000. Many organisations like to promote their Gartner or Forrester rating when it is very positive and may provide access to the reports themselves. -
References
1. Design Patterns: Elements of Reusable Object-Oriented Software, Gamma, E., Helm, R., Johnson, R., Vlissides, J., Pearson, 1995.
2. Design Patterns Explained Simply, Shvets, A., 🔗 www.sourcemaking.com
3. 🔗 http://www.dofactory.com/net/design-patterns (GoF patterns in C++)
4. 🔗 https://www.ibm.com/developerworks/java/tutorials/j-patterns/j-patterns.html (GoF patterns in Java)
5. 🔗 http://www.hillside.net/patterns/patterns-catalog (variety, general)
6. 🔗 http://www.welie.com/index (interaction design)
7. 🔗 www.enterpriseintegrationpatterns.com/
8. 🔗 https://martinfowler.com/eaaCatalog/
9. 🔗 https://msdn.microsoft.com/en-us/library/ff649977.aspx
10. 🔗 https://www.oracle.com/webfolder/ux/middleware/alta/patterns/index.html
11. 🔗 https://www.tutorialspoint.com/design_pattern/
12. 🔗 https://www.safaribooksonline.com/library/view/head-first-design/0596007124/
13. 🔗 http://gameprogrammingpatterns.com/
14. Agile Software Development, Principles, Patterns, and Practices, Martin, R., Pearson New International Edition Paperback, 2013.
15. Patterns of Enterprise Application Architecture, Fowler, M., Addison-Wesley, 2003
-
Appendix 1: Video Clips explaining the GoF Patterns Creational Purpose Factory Method Recycle objects no longer in use to create instance of several derived classes 📹 Factory Design Pattern Abstract Factory Creates an instance of several families of classes 📹 Abstract Factory Design Pattern Builder Separates object construction from its representation 📹 Builder Design Pattern Object Pool Avoid expensive acquisition and release of resources by 📹 [Unity 5] Object Pooling Tutorial Prototype A fully initialized instance to be copied or cloned 📹 Prototype Design Pattern Tutorial Singleton A class of which only a single instance can exist 📹 Singleton Design Pattern Tutorial Structural Purpose Adapter Match interfaces of different classes 📹 Adapter Design Pattern Bridge Separates an object’s interface from its implementation 📹 Bridge Design Pattern Composite A tree structure of simple and composite objects 📹 Composite Design Pattern Decorator Add responsibilities to objects dynamically 📹 Decorator Design Pattern Façade A single class that represents an entire subsystem 📹 Facade Design Pattern Flyweight A fine-grained instance used for efficient sharing 📹 Flyweight Design Pattern Private Class Data Restricts accessor/mutator access 📹 Private Data Class Proxy An object representing another object Behavioural Purpose Chain of Responsibility A way of passing a request between a chain of objects 📹 Chain of Responsibility Command Encapsulate a command request as an object 📹 Command Design Pattern Interpreter A way to include language elements in a program 📹 Interpreter Design Pattern Iterator Sequentially access the elements of a collection 📹 Iterator Design Pattern Mediator Defines simplified communication between classes 📹 Mediator Design Pattern Memento Capture and restore an object's internal state 📹 Memento Design Pattern Null Object Designed to act as a default value of an object 📹 The Null Object Pattern Observer A way of notifying change to a number of classes 📹 Observer Design Pattern State Alter an object's behaviour when its state changes 📹 State Design Pattern Strategy Encapsulates an algorithm inside a class 📹 Strategy Design Pattern Template Method Defer the exact steps of an algorithm to a subclass 🔗 Microsoft Patterns and Practices Visitor Defines a new operation to a class without change 📹 Visitor Design Pattern Sidebar: MVC Implementation Issues
Forms are enclosed in the HTML form tag. This tag specifies the communication endpoint the data entered into the form should be submitted to, and the method of submitting the data, GET or POST. Forms can be made up of standard graphical user interface elements. Forms are usually combined with programs written in various programming languages to allow developers to create dynamic web sites. The most popular languages include both client-side and/or server-side languages. On the Client-side the de facto client-side scripting language for web sites is JavaScript. Using JavaScript on the Document Object Model (DOM) leads to the method of Dynamic HTML that allows dynamic creation and modification of a web page within the browser. While client-side languages used in conjunction with forms are limited, they often can serve to do pre-validation of the form data and/or to prepare the form data to send to a server-side program. Server-side code can do a vast assortment of tasks to create dynamic web sites — from authenticating a login, to retrieving and storing data in a database, to spell checking, to sending e-mail — quite unlike client-side programs. A significant advantage to server-side over client-side execution is the concentration of functionality onto the server rather than relying on different web browsers to implement various functions in consistent, standardised ways. In addition, processing forms on a server often results in increased security if server-side execution is designed not to trust the data supplied by the client and includes such techniques as HTML sanitisation. Some of the interpreted languages commonly used to design interactive forms in web development are PHP, Python, Ruby, Perl, JSP, Adobe ColdFusion and some of the compiled languages commonly used are Java and C# with ASP.NET.
ASP.NET Web Forms is a part of the ASP.NET web application framework and is included with Visual Studio. It is one of the four programming models you can use to create ASP.NET web applications, the others are ASP.NET MVC, ASP.NET Web Pages, and ASP.NET Single Page Applications. ASP .NET Web Forms are pages that your users request using their browser. These pages can be written using a combination of HTML, client-script, server controls, and server code. When users request a page, it is compiled and executed on the server by the framework, and then the framework generates the HTML markup that the browser can render. An ASP.NET Web Forms page presents information to the user in any browser or client device.
Using Visual Studio, you can create ASP.NET Web Forms. The Visual Studio Integrated Development Environment (IDE) lets you drag and drop server controls to lay out your Web Forms page. You can then easily set properties, methods, and events for controls on the page or for the page itself. These properties, methods, and events are used to define the web page's behaviour, look and feel, and so on. To write server code to handle the logic for the page, you can use a .NET language like Visual Basic or C#.
- The main advantages of ASP.net MVC are:
- Enables the full control over the rendered HTML.
- Provides clean separation of concerns(SoC).
- Enables 🔗 Test Driven Development (TDD).
- Easy integration with JavaScript frameworks.
- Following the design of stateless nature of the web.
- RESTful urls that enables SEO.
- No ViewState and PostBack events.