.NET Best Practices and Design Patterns Flashcards
Decorator Pattern
Increases complexity setting up the chain of decorators.
Supports the Open/Close Principle.
Decorated object is not the object.
Decorator in the .NET Framework
Stream classes use decorators.
BufferedStream and CryptoStream classes decorate a Stream.
Adapter Pattern
Translates one interface for a class into a compatible interface.
An adapter allows classes to work together that normally could not because of incompatible interfaces, by providing its interface to clients while using the original interface. The adapter translates calls to its interface into calls to the original interface, and the amount of code necessary to do this is typically small. The adapter is also responsible for transforming data into appropriate forms.
Adapter Pattern Implementation
Find Commonality: Commonality is extracted to an interface
Encapsulate Differences: Incompatible classes are wrapped by an adapter
Client works with the adapter class
Adapter Pattern in the .NET Framework
DataAdapter classes convert the interfaces of ventor-specific database classes into an interface that works with the general DataSet class: SqlDataAdapter, OdbcDataAdapter, etc.
DataSet class in namespace System.Data.
Template Method Pattern
Defines the program skeleton of an algorithm in a method, called template method, which defers some steps to subclasses.
It lets one redefine certain steps of an algorithm without changing the algorith’s structure.
Template Method Pattern Implementation
Find Commonality: Common parts of the algorithm are factored into a base class.
Encapsulate Differences: Differences (customization points) are encapsulated in derived classes.
Allows the customization points to be seamlessly integrated.
Template Method Pattern in the .NET Framework
The sequence of events for a form is fixed. The details of the steps are customizable.
SOLID Principles
Single Responsibility Principle: A class should have only one reason to change
Open/Closed Principle: Classes should be open to extension and closed to modification
Liskov Substitution Principle: Derived classes should honor the base class’ contract Interface
Segregation Principle:
Dependency Inversion Principle:
Single Responsibility
Class should have a single responsibility, and that responsibility should be entirely encapsulated by the class.
All its services should be narrowly aligned with that responsibility.
Open/Closed Principle (OCP)
Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.
Entities can allow their behaviour to be modified without altering its source code. This is especially valuable in a production environment, where changes to source code may necessitate code reviews, unit tests, and other such procedures to qualify it for use in a product: code obeying the principle doesn’t change when it is extended, and therefore needs no such effort.
Liskov Substitution
Derived classes must be substitutable for their base classes.
Derived classes must be consistent with the promises made by the base class’ contract. Derived classes add data, add behavir, but do not remove behavior.
Interface Segregation Principal (ISP)
Interfaces are owned by clients, not implementors.
No client should be forced to depend on methods it does not use. ISP splits interfaces which are very large into smaller and more specific ones so that clients will only have to know about the methods that are of interest to them. Such shrunken interfaces are also called role interfaces. ISP is intended to keep a system decoupled and thus easier to refactor, change, and redeploy.
Dependency Inversion Principal
Details depend on abstraction.
Isolates business logic from data access logic. Allows us to write a strategy for data access, so it can be faked. Specific form of decoupling where conventional dependency relationships established from high-level, policy-setting modules to low-level, dependency modules are inverted (i.e. reversed) for the purpose of rendering high-level modules independent of the low-level module implementation details. The principle states: A. High-level modules should not depend on low-level modules. Both should depend on abstractions. B. Abstractions should not depend upon details. Details should depend upon abstractions.
Role Object Pattern
Adapt an object to different client’s needs through transparently attached role objects, each one representing a role the object has to play in that client’s context.
The object manages its role set dynamically. By representing roles as individual objects, different contexts are kept separate and system configuration is simplified. Uses delegation to solve the problem of roles.
Which gives more run-time flexibility: composition or inheritance?
Composition
What tests can help determine correctness of inheritance?
N/A
Is it better to depent on wider or narrower interfaces?
Narrower
Repository Pattern
Separates the querying from the filtering.
Matches method -Returns Ienumerable -Passed a filter object Icriteria -Can handle the three standard return cases: None, One, Lots Add method Remove method SaveChanges method
Mock Object Pattern
TestInitialize attibute
N/A
ClassInitialize attribute
N/A