Preface
In this chapter, we are going to explain the fourth chapter of the implementation of the five major principles of SOLID JavaScript, the Interface Segregation Principle.
Original English text: http://freshbrewedcode.com/derekgreeer/2012/01/08/solid-javascript-the-interface-segregation-principle/
Note: The author of this article is quite touching, so the uncle is also depressed to understand it. Just read it as you please, don't get stuck in it.
The description of the principle of interface isolation is:
The code copy is as follows:
Clients should not be forced to depend on methods they do not use.
Customers should not be forced to rely on methods they do not use.
When the interface method that the user depends on is only used by other users and does not use it, it must implement these interfaces. In other words, if a user relies on an interface that is not used but used by other users, when other users modify the interface, all users relying on the interface will be affected. This obviously violates the principle of opening and closing, and is not what we expect.
Interface isolation principle ISP is somewhat similar to single responsibility. Both are used to aggregate functional responsibilities. In fact, ISP can be understood to convert programs with single responsibilities to an object with a public interface.
JavaScript interface
How do we abide by this principle under JavaScript? After all, JavaScript does not have the feature of interfaces. If the interface is what we want to establish contract and decouple through abstract types provided by a certain language, it can be said that it is OK, but JavaScript has another form of interface. In the book Design Patterns Elements of Reusable Object-Oriented Software we found the definition of the interface:
http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612
Any operation declared by an object contains an operation name, parameter object, and return value of the operation. We call it the signature of the operator.
All operations declared in an object are called the interface of this object. An object's interface depicts all request information that occurs on this object.
Regardless of whether a language provides a separate construct to represent an interface, all objects have an implicit interface composed of all properties and methods of the object. Refer to the following code:
The code copy is as follows:
var exampleBinder = {};
exampleBinder.modelObserver = (function() {
/* Private variable*/
return {
observe: function(model) {
/* Code*/
return newModel;
},
onChange: function(callback) {
/* Code*/
}
}
})();
exampleBinder.viewAdaptor = (function() {
/* Private variable*/
return {
bind: function(model) {
/* Code*/
}
}
})();
exampleBinder.bind = function(model) {
/* Private variable*/
exampleBinder.modelObserver.onChange(/* callback callback */);
var om = exampleBinder.modelObserver.observe(model);
exampleBinder.viewAdaptor.bind(om);
return om;
};
The above exampleBinder class library implements two-way binding. The public interface exposed by this class library is the bind method, where the functions of change notification and view interaction used in bind are implemented by separate objects modelObserver and viewAdaptor, respectively. These objects are in a sense the specific implementation of the public interface bind method.
Although JavaScript does not provide interface types to support object contracts, the implicit interface of the object can still be provided to program users as a contract.
ISP and JavaScript
Some of the subsections we discuss below are the impact of violating the interface isolation principle in JavaScript. As seen above, although it is a pity to implement the principle of interface isolation in JavaScript programs, it is not as powerful as statically typed languages. The language characteristics of JavaScript sometimes make the so-called interface a little non-stick.
The realization of depravity
In statically typed languages, one of the reasons for violating ISP principles is the degenerate implementation. The methods defined in all interfaces in Java and C# must be implemented. If you only need a few of them, the other methods must also be implemented (can be implemented by empty or throwing exceptions). In JavaScript, if only some interfaces in an object are needed, it cannot solve the problem of degenerate implementation, although there is no need to force the implementation of the above interface. However, this implementation still violates the principle of Richter replacement.
The code copy is as follows:
var rectangle = {
area: function() {
/* Code*/
},
draw: function() {
/* Code*/
}
};
var geometryApplication = {
getLargestRectangle: function(rectangles) {
/* Code*/
}
};
var drawingApplication = {
drawRectangles: function(rectangles) {
/* Code*/
}
};
When a rectangle alternative to satisfy the getLargestRectangle of the new object geometryApplication, it only needs the rectangle area() method, but it violates the LSP (because it cannot use the draw method that can only be used in the drawRectangles method).
Static coupling
Another reason for ISP violations in statically typed languages is static coupling. In statically typed languages, interfaces play a major role in a loosely coupled design program. Whether in a dynamic or static language, sometimes an object may need to communicate between multiple client users (such as shared state). For statically typed languages, the best solution is to use Role Interfaces, which allows the user to interact with the object (which may need to be in multiple roles) as its implementation to decouple the user and unrelated behavior. There is no such problem in JavaScript, because objects are decoupled by the unique advantages of dynamic languages.
Semantic coupling
One common reason for violating ISP is both dynamic and statically typed languages, which is semantic coupling. The so-called semantic coupling is interdependence, that is, the behavior of an object depends on another object, which means that if a user changes one of the behaviors, it is likely to affect another user. This also violates the principle of single responsibility. This problem can be solved by inheritance and object substitution.
Scalability
Another reason for the problem is about scalability. Many people will give examples about callback to demonstrate scalability (such as the callback settings after success in ajax). If such an interface needs an implementation and there are many familiar or methods in the object of this implementation, the ISP will become very important. That is to say, when an interface interface becomes a need to implement many methods, its implementation will become extremely complex, and it may cause these interfaces to assume a non-sticky responsibility. This is the fat interface we often mention.
Summarize
The dynamic language characteristics in JavaScript make our implementation of non-stick interfaces less influential than statically typed languages, but the principle of interface isolation still has its function in the JavaScript programming model.