Category: Software deisgn

Stateful vs Stateless web server design

http://orca.st.usm.edu/~seyfarth/network_pgm/net-6-3-3.html

  • A stateful server remembers client data (state) from one request to the next.
  • A stateless server keeps no state information
  • Using a stateless file server, the client must
    specify complete file names in each request
    specify location for reading or writing
    re-authenticate for each request
  • Using a stateful file server, the client can send less data with each request
  • A stateful server is simpler
  • On the other hand a stateless server is more robust
    lost connections can’t leave a file in an invalid state
    rebooting the server does not lose state information
    rebooting the client does not confuse a stateless server

 

https://sites.google.com/site/assignmentssolved/mca/semester5/mc0085/11

Stateful Versus Stateless Servers

The file servers that implement a distributed file service can be stateless or Stateful. Stateless file servers do not store any session state. This means that every client request is treated independently, and not as a part of a new or existing session. Stateful servers, on the other hand, do store session state. They may, therefore, keep track of which clients have opened which files, current read and write pointers for files, which files have been locked by which clients, etc.

The main advantage of stateless servers is that they can easily recover from failure. Because there is no state that must be restored, a failed server can simply restart after a crash and immediately provide services to clients as though nothing happened. Furthermore, if clients crash the server is not stuck with abandoned opened or locked files. Another benefit is that the server implementation remains simple because it does not have to implement the state accounting associated with opening, closing, and locking of files.

The main advantage of Stateful servers, on the other hand, is that they can provide better performance for clients. Because clients do not have to provide full file information every time they perform an operation, the size of messages to and from the server can be significantly decreased. Likewise the server can make use of knowledge of access patterns to perform read-ahead and do other optimizations. Stateful servers can also offer clients extra services such as file locking, and remember read and write positions.

 

Another good website to read:

http://www.cs.jhu.edu/~yairamir/cs418/os10/tsld018.htm

Web Cache and HTTP

Caching Tutorial for Web Authors and Webmasters

https://www.mnot.net/cache_docs/#SCRIPT

HTTP Made Really Easy
A Practical Guide to Writing Clients and Servers
http://www.jmarshall.com/easy/http/

 

http://stackoverflow.com/questions/2092527/what-happens-when-you-type-in-a-url-in-browser

http://www.quora.com/Programming-Interviews/What-happens-when-you-type-google-com-into-your-browsers-address-bar

In an extremely rough and simplified sketch, assuming the simplest possible HTTP request, no proxies and IPv4 (this would work similarly for IPv6-only client, but I have yet to see such workstation):

  1. browser checks cache; if requested object is in cache and is fresh, skip to #9
  2. browser asks OS for server’s IP address
  3. OS makes a DNS lookup and replies the IP address to the browser
  4. browser opens a TCP connection to server (this step is much more complex with HTTPS)
  5. browser sends the HTTP request through TCP connection
  6. browser receives HTTP response and may close the TCP connection, or reuse it for another request
  7. browser checks if the response is a redirect (3xx result status codes), authorization request (401), error (4xx and 5xx), etc.; these are handled differently from normal responses (2xx)
  8. if cacheable, response is stored in cache
  9. browser decodes response (e.g. if it’s gzipped)
  10. browser determines what to do with response (e.g. is it a HTML page, is it an image, is it a sound clip?)
  11. browser renders response, or offers a download dialog for unrecognized types

Again, discussion of each of these points have filled countless pages; take this as a starting point. Also, there are many other things happening in parallel to this (processing typed-in address, adding page to browser history, displaying progress to user, notifying plugins and extensions, rendering the page while it’s downloading, pipelining, connection tracking for keep-alive, etc.).

 

TCP 3-Way Handshake

TCP 3-Way Handshake
TCP 3-Way Handshake
TCP 3-Way Handshake

http://www.inetdaemon.com/tutorials/internet/tcp/3-way_handshake.shtml

Factory Method Pattern (Head First DP)

Code UP Close:
A factory method handles object creation and encapsulates it in a subclass. This decouples the client code in the superclass from
the object creation code in the subclass.

abstract Product factoryMethod(String type)

A factory method is abstract so the subclass are counted on to handle object creation
A factor method returns a Product that is typically used within methods defined in the superclass
A factory method isolates the client ( the code in the superclass, like orderPizza()) from knowing what kind of concrete Product is actually created

Formal definition of Factory Method Pattern: (Page 134)

        The Factory Method Patterndefi nes an interface for creating an object, but lets subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclass

As with every factory, the Factory Method Pattern gives us a way to encapsulate the instantiations of concrete types. The abstract Creator gives you an interface with a method for creating objects, also known as the “factory method.” Any other methods implemented in the abstract Creator are written to operate on products produced by the factory method.

The creator is a class that contains the implementation for all of the methods to manipulate products, except for the factory method; The abstract factoryMethod() is what all Creator subclasses must implement.

Only subclasses actually implement the factory method and create products.Only subclass (concreatCreator) is responsible for creating one or more concrete products. It is the only class that has the knowledge of how to create these products.

As in the official definition, you’ll often hear developers say that the Factory Method lets subclasses decide which class to instantiate. They say “decides” not because the pattern allows subclasses themselves to decide at runtime, but because the creator class is written without knowledge of the actual products that will be created, which is decided purely by the choice of the subclass that is used.

 

Another design principle (Dependency Inversion Principle):

Depend upon abstractions. Do not  depend upon concrete classes.

Head first design pattern: Observer

The Observer Patterndefines a one-to-many dependency between objects so that when one object changes state, all of its dependents are
notified and updated automatically.

Even though the java have builti-in support for observer pattern, with Observable, and Observer, sometimes we still have to roll our own implementation.

Note: shortcomings of built-in Observable in Java:

violate our OO design principle of programming to interfaces not  implementations. Observable is a class, and we have to subclass it. as we know, a class that already extends another superclass won’t be able to sublcass Observable.

2nd principle violated : favor composition over inheritance. Why?  Observable protects crucial methods: the setChanged() method is protected. This means you can call setChanged()  only if you’ve subclassed Observable. This means you can’t even create an instance of the Observable class and compose it with your own objects, you have to subclass.

Note: Design Principle III:

Strive for loosely coupled designs  between objects that interact.

 

How to use Java’s Observer Pattern:

For an object to become an observer, as usual, implements the observer interface (this time the java.util.Observer interface) and call addObserver() on any Observable object. Likewise, to remove yourself as an observer just call deleteObserver().

For the Observable to send notification. First of all you need to be Observable by extending the java.util.Observable
superclass. From there it is a two step process: 1. You first must call the setChanged() method to signify that the state has changed in your object.

2 .Then, call one of two notifyObservers() method:   either notifyObservers() , which means  we’re using the PULL model;  or notifyObservers(Object arg), correspondng to PUSH model

Head first design pattern (1) Strategy pattern

What I have learned in the first chapter:

Design principle (1) : Separate what varies from what not vary

(2) program to interface, instead of implementation

(3) Favor composition over inheritance: time spent after development, like maintaining and extension costs more time than developing itself. Thus we should not emphasize reuse over maintainability and extensibility. Composition is a better way to achieve code reuse because it is a better compromise between code reuse and maintainability. Another problem with inheritance not mentioned in this textbook, as it is not related with design pattern, is diamond problem, which is talked about in another article posted in my blog (copied from wikepedia)

The Strategy  pattern used in the first example, SimuDuck, is defined as:  “The strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.”

The set of class that implements the interface “flybehavior”, “quackbehavior”, is a set of algorithm encapsulated.

Most patterns and principles address issues of change in software.

Most patterns allow some part of a system to vary independently of all other parts.

RAII: Resource Acquisition Is Initialization

http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization

http://www.hackcraft.net/raii/

http://stackoverflow.com/questions/417481/pointers-smart-pointers-or-shared-pointers

Resource Acquisition Is Initialization

The technique was invented by Bjarne Stroustrup[1] to deal with resource deallocation in C++. In this language, the only code that can be guaranteed to be executed after an exception is thrown are the destructors of objects residing on the stack.

RAII is vital in writing exception-safe C++ code: to release resources before permitting exceptions to propagate (in order to avoid resource leaks) one can write appropriate destructors once rather than dispersing and duplicating cleanup logic between exception handling blocks that may or may not be executed.

RAII can be used with:

  • Languages which can have user-defined types allocated on the stack (“automatic” objects in C/C++ terminology) and cleaned up during normal stack cleanup (whether because of a function returning, or an exception being thrown). E.g. C++.
  • Languages which have reference-counted garbage collection and hence predictable cleanup of an object for which there is only one reference. E.g. VB6

RAII cannot generally be used with languages that clean up objects using an unpredictable garbage collection, such as Java (however see the Postscript on .NET). If a language guarantees cleanup of all objects before an application shuts down then it may be applicable to some problems.

C++ and D allow objects to be allocated on the stack and their scoping rules ensure that destructors are called when a local object’s scope ends. By putting the resource release logic in the destructor, C++’s and D’s scoping provide direct support for RAII.

The C language does not directly support RAII, though there are some ad-hoc mechanisms available to emulate it. However, some compilers provide non-standard extensions that implement RAII. For example, the “cleanup” variable attribute extension of GCC is one of them.

It’s worth noting that if you are using C++ with garbage collection (which isn’t defined by the language, but which may be provided by a run time) then that garbage collection will generally not apply to objects allocated on the stack and hence RAII can still be used.

RAII only ensures that the resource in question is released appropriately; care must still be taken to maintain exception safety. If the code modifying the data structure or file is not exception-safe, the mutex could be unlocked or the file closed with the data structure or file corrupted.

Local variables easily manage multiple resources within a single function: They are destroyed in the reverse order of their construction, and an object is only destroyed if fully constructed. That is, if no exception propagates from its constructor.

Resource management without RAII

Finalizers

In Java, objects are not allocated on the stack and must be accessed through references; hence, one cannot have automatic variables of objects that “go out of scope”. Instead, all objects are dynamically allocated. In principle, dynamic allocation does not make RAII unfeasible per se; it could still be feasible if there were a guarantee that a “destructor” (“finalize”) method would be called as soon as an object were pointed to by no references (i.e., if the object lifetime management were performed according to reference counting).

However, Java objects have indefinite lifetimes which cannot be controlled by the programmer, because, according to the Java Virtual Machine specification, it is unpredictable when the garbage collector will act. Indeed, the garbage collector may never act at all to collect objects pointed to by no references. Hence the “finalize” method of an unreferenced object might never be called or be called long after the object became unreferenced. Resources must thus be closed manually by the programmer, using something like thedispose pattern.

Disadvantages of scope bound resource management alternatives

Where both finalizers and closure blocks work as a good alternative to RAII for “shallow” resources, it is important to note however that the compositional properties of RAII differ greatly from these scope bound forms of resource management. Where RAII allows for full encapsulation of resources behind an abstraction, with scope bound resource management this isn’t the case. In an environment that purely depends on scope bound resource management, “being a resource” becomes a property that is transitive to composition. That is, using only scope bound resource management, any object that is composed using a resource that requires resource management effectively itself becomes a resource that requires resource management. RAII effectively breaks the transitivity of this property allowing for the existence of “deep” resources to be effectively abstracted away.

Lets for example say we have an object of type A that by composition holds an object of type B that by composition holds an object of type C. Now lets see what happens when we create a new implementation of C that by composition holds a resource R. R will have some close or release method that must be invoked prior to C going out of scope. We could make C into a RAII object for R that invokes release on destruction.

Basically now we have the situation where from the point of view of R and C (shallow resources), scope bound resource management alternatives functionally are fully equivalent to RAII. From a point of view of A and B (deep resources) however, we see a difference in the transitivity of “being a resource” emerging. With C as a RAII object, the interface and implementation of A, B and any code using a scoped A or B will remain unchanged and unaware of the newly introduced existence of “deep” resources. Without RAII however, the fact that C holds R means that C will need its own release method for proxying the release of R. B will now need its own releasemethod for proxying the release of C. A will need its own release method for proxying the release of B, and the scope where either A or B is used will also require of the alternative resource management techniques, where with RAII C provides the abstraction barrier that hides the implementation detail of “implemented using a resource” from the view of A, B and any users of an A or B. This difference shows that RAII effectively breaks the compositional transitivity of the “being a resource” property.

Composition over inheritance & Diamond problem (cited from Wikepedia)

http://en.wikipedia.org/wiki/Composition_over_inheritance

http://en.wikipedia.org/wiki/Diamond_problem

Composition over inheritance in object-oriented programming is a technique by which classes may achieve polymorphic behavior and code reuse by containing other classes which implement the desired functionality instead of through inheritance.[1]

This technique is also referred to as “Composite Reuse Principle”.

Basics

An implementation of composition over inheritance typically begins with the creation of various interfaces representing the behaviors which the system must exhibit. The use of interfaces allows this technique to support the polymorphic behavior that is so valuable in object-oriented programming. Classes implementing the identified interfaces are built and added to Business Domain classes as needed. Thus system behaviors are realized without inheritance. In fact, business domain classes may all be base classes without any inheritance at all. Alternative implementation of system behaviors are accomplished by providing another class which implements the desired behavior interface. Any business domain class that contains a reference to the interface can easily support any implementation of that interface and the choice can even be delayed until run time.

Example

[edit]Inheritance

class Object {
  public:
     virtual void update() {} ;
     virtual void draw() {} ;
     virtual void collide(Object objects[]) {} ;
};
class Visible : public Object {
  public:
     virtual void draw() { /* draw model at position of this object*/ };
  private:
     Model* model;
};
class Solid : public Object {
  public:
     virtual void collide(Object objects[]) { /*check and react to collisions with objects */ };
};
class Movable : public Object {
  public:
     virtual void update() { /* update position */ };
};

Then we have concrete classes:

  • class Player – which is Solid, Movable and Visible
  • class Cloud – which is Movable and Visible, but not Solid
  • class Building – which is Solid and Visible, but not Movable
  • class Trap – which is Solid and not Visible nor Movable

Using inheritance we either have to do multiple inheritance, which leads to the diamond problem, or make classes like VisibleAndSolid, VisibleAndMovable, VisibleAndSolidAndMovable, etc. for every needed combination, which leads to a large amount of repetitive code.

[edit]Composition (and a little inheritance)

class Object {
  public:
    Object(VisibilityDelegate* v, UpdateDelegate *u, CollisionDelegate *c):_v(v),_u(u),_c(c) {};

    void update() { _u->update(); };
    void draw()   { _v->draw(); };
    void collide(Object objects[]) { _c->collide(objects); };
  private:
    VisibilityDelegate* _v;
    UpdateDelegate *_u;
    CollisionDelegate *_c;
};

class VisibilityDelegate {
  public:
     virtual void draw() = 0;
};
class Invisible : public VisibilityDelegate {
  public:
     virtual void draw() {};
};
class Visible: public VisibilityDelegate {
  public:
     virtual void draw() { /*draw model*/ };
};

class CollisionDelegate {
  public:
     virtual void collide(Object objects[]) = 0;
};
class Solid : public CollisionDelegate {
  public:
     virtual void collide(Object objects[]) { /* check collisions with object and react*/ };
};
class NotSolid : public CollisionDelegate {
  public:
    virtual void collide(Object objects[]) {};
};

class UpdateDelegate {
  public:
     virtual void update() = 0;
};
class Movable : public UpdateDelegate {
  public:
     virtual void update() { /*move object*/ };
};
class NotMovable : public UpdateDelegate {
  public:
     virtual void update() { };
};

Then concrete classes would look like:

class Player : public Object {
  public:
    Player():Object(new Visible(), new Movable(), new Solid()) {};
...
};
class Smoke : public Object {
  public:
    Smoke():Object(new Visible(), new Movable(), new NotSolid()) {};
...
};

Benefits

Composition over inheritance can simplify the initial design of Business Domain classes and provide a more stable business domain in the long term. Its advantage over inheritance is a more thorough isolation of interests than can be described by a hierarchy of descendant classes. Additionally, inheritance models are often contrived during the definition of business domain classes in order to make sense of the information in the problem domain and do not necessarily reflect the true relationship of various system objects.

Initial design is simplified by identifying system object behaviors in separate interfaces instead of creating a hierarchical relationship to distribute behaviors among business domain classes via inheritance. This approach more easily accommodates future requirements changes that would otherwise require a complete restructuring of business domain classes in the inheritance model. Additionally, it avoids problems often associated with relatively minor changes to an inheritance-based model that includes several generations of classes.

Diamond Problems: 

In object-oriented programming languages with multiple inheritance, the diamond problem (sometimes referred to as the “deadly diamond of death[1]) is an ambiguity that arises when two classes B and C inherit from A, and class D inherits from both B and C. If D calls a method defined in A (and does not override the method), and B and C have overridden that method differently, then from which class does it inherit: B, or C?

For example, in the context of GUI software development, a class Button may inherit from both classes Rectangle (for appearance) and Clickable (for functionality/input handling), and classes Rectangle and Clickable both inherit from the Object class. Now if the equals method is called for a Button object and there is no such method in the Button class but there is an overridden equals method in both Rectangle andClickable, which method should be eventually called?

Business domain:

business domain in object oriented programming is the set of classes that represent objects in the business model being implemented. The business domain is distinguishable from the business model in that the business model is an understanding and explanation of information and behaviors in the problem domain while the business domain is an implementation of that model in a specific programming language.

Domain model:

domain model in problem solving and software engineering can be thought of as a conceptual model of a domain of interest (often referred to as a problem domain) which describes the various entities, their attributes, roles and relationships, plus the constraints that govern the integrity of the model elements comprising that problem domain.

An important advantage of a domain model is that it describes and constrains the scope of the problem domain. The domain model can be effectively used to verify and validate the understanding of the problem domain among various stakeholders. It is especially helpful as a communication tool and a focusing point both amongst the different members of the business team as well as between the technical and business teams.

In UML, a class diagram is used to represent the domain model.