Oo essay (with the Supplement of the Connection Pool series, Bonmot
Speaking of OO, everyone has everyone's own opinion. The shallow people such as "Obj.Method's grammar is OO"; "DeSign Pattern". Today I also said that I have seen my hole.
What is OO? Is an interface programming. Whether you use vTable, or GP's Function Object, or is a function of C, orthogonal decomposition is also good, all Pattern is also an implementation for interface programming ideas.
Why do you want to program? In order to decouple.
What is decoupled? That is to divide the module that is not related to or limited in the program. Just like a package, you want to put different things in different places. Pour the soy sauce and vinegar into different bottles. Here, it is possible to simply implement it for completely unrelated functions. But in fact, in many cases, there is a relationship between different modules. At this time, the interface is required. Use the interface to accurately define the relationship between the modules. Before the decoupling, all information is shared between the two modules (this information includes data, and also the respective implementation details). After the decoupling, the information that needs to be shared is accurately defined in the interface. At the same time, the flow direction of information is also determined.
What is the benefits of decoupling? First, the program becomes clear. Second, the details of the exposed implementation are hidden. The modification of the code is easy. Again, the structure is flexible, and one module can be collapsed by a module and an arbitrary implementation interface. Original class A can only cooperate with class B, after decoupling, and all classes of all implementation interface IBs such as B1, B2, ... The extensibility is greatly enhanced. Naturally, the code is reused. There is no compilation dependence. You can concentrate on writing and compile a module without waiting for the completion of other modules. Debugging is easy. As long as the module is debugged to an interface, there is no problem with other interfaces. Thus, it is even possible to debug the Dummy class of this interface with a Simple Naive. (This, using template's GP does not apply)
So what is the disadvantage of decoupling? The definition of the interface is critical. Decoupling is hidden information to define some information that needs to be shared. If the interface is defined, it hides the information that is not hidden, then this decoupling is failed for some complexity of this information. And if there is no information that should be hidden, the coupling should still exist.
So how to decouple, how to define an interface? This is a thinking process of pure business logic. Here, the knowledge of the programming language has become irrelevant. In fact, as long as it is accurately grasping the needs, strictly analyzes the needs of demand and internal submodules in the module, anyone who is logically thinking can be competent. Just like the songs of Singer, although I don't know how to know, I will write songs, but I don't have to understand the songs. The principle of decoupling is simple: precise definition requirements, carefully analyze the needs. Don't hide any "demand" may need information. Don't let go of any "demand" information. The situation is unclear, I would rather a thousand, I can't kill one. All in all, I can't hide the information that may be needed. If reuse is not considered, reuse is the natural result of decoupling. Can't fall because of the fruit!
As for the specific use of these principles, it has been reflected in the article in the previous connection pool.
Below, I will answer questions about Bonmot's example of my Connection Pool. Finally, give my solve ideas for a problem with Bonmot.
None of the problem: 1.connectionFactoryImpl can also inherit the connectionFactory
In fact, I originally implemented, it is indeed ConnectoInfactoryImpl Implements ConnectionFactory, but later, when I Overload instance () function, I found that the code of the ConnectionFactory of the two functions returned is different. So, anonymous class was born. Here, there is a little worthy of boasting, hiding the constructor, making the Customer code using ConnectionFactoryIMPL is completely unsatisfactory. This is why I have always advocated the reason for hiding the constructor. The following is a class implementation: public class ConnectionFactoryImpl {private ConnectionFactoryImpl () {} static public ConnectionFactory instance (final String driver, final String url, final String user, final String pwd) throws SQLException, ClassNotFoundException {final Class driverClass = Class.forName (driver); return new ConnectionFactory () {private final Class keeper = driverClass; public final Connection createConnection () throws SQLException {return DriverManager.getConnection (url, user, pwd);}};} static public ConnectionFactory instance (final String driver , final String url) throws SQLException, ClassNotFoundException {final Class driverClass = Class.forName (driver); return new ConnectionFactory () {private final Class keeper = driverClass; public final Connection createConnection () throws SQLException {return DriverManager.getConnection (url) }};}} 2. ConnectionFactoryImpl Private Final Class Keeper = DriverClass; // seems to be redundant
Yes, a lot of code is bare Class.Forname (classname). It is also very good. However, remember which article has been seen in this article, in the new Java Language Specification, dynamically loaded classes may be collected by garbage. If this is the case, then? I am easy for class.Forname () to load the Driver class, so! Which day JVM is happy to recover me! So 咱 咱 防 防 防!
The problem 1.connectionPooling is an algorithm for implementing Pool, which is getConnection (). Why does ReleaseConnection (CONN) does not directly define the ReleaseConnection () method directly, but more Interface ConnectionHome
First, my ConnectionPool interface is used directly to users. I have proposed it in the first chapter of this article, which is not good to expose the user. "Connection is not good. How do you guarantee that the user does not return to the SQL Server connection to the Oracle connection pool? How to ensure that the user does not return the same connection twice to the connecting pool? There is already Connection.Close (), why is the user to call the ReleaseConnection? The ConnectionHome interface is defined by the PooledConnection class. PooledConnection is a class that works with pool in physical Connection. It needs to know how to return a physical connection. The ConnectionHome interface only defines a method: Void ReleaseConnection (connection), is a product description of this demand.
2. Things are always right, Factory is used to implement physical connections, and should also be responsible for shutting down physical connections without closing the Pooling algorithm to the physical connection. In addition, obtaining and closing the Connection should be implemented in an interface. If it is divided into two interfaces, the implementation of the connection must not be guaranteed to be implemented. That is, Factory is a physical layer, and Pool is a Cache layer, and the client is an application layer.
First, ConnectionPool is an interface to describe the Pooling algorithm, which needs to represent all possible POOLING algorithms, so we cannot exclude in some type of Pooling algorithm, it will connect to the physical database connection at a certain logic. Therefore, the POOLING algorithm must be able to close this connection at any time. As for calling connect.close (), or put a CloseConnection method in ConnectionFactory, let's take a look at some other Factory implementations. In COM, the IFActory interface is responsible for the production of objects. But the release object is responsible for IUNKNOWN :: Release (). In Java, many Factory interfaces are responsible for the production of objects, but garbage collection is responsible for recycling objects. Why does these Factory mechanisms do not require producers to destroy the object? The reason is that type is safe! For example: Class factory {public object getObject () {if (...) return new classa (); else return new classb ();} public void release (object obj) {if (obj is classa) { Classa) obj) .closea ();} else {((Classb) obj) .closeb ();} / * ugly! In such a factory, the getObject method knows the real type of the object produced. But after returning, the real type of the object is lost. In this way, if you send the object again to the factory, "Hey! This is from your factory, now I don't have to, I will give you." For the factory, it needs: 1, confirm that this object is really Factory. (This is not so easy) 2, confirm how this object makes it. In order to find the corresponding destruction mechanism (nor is it easy) Why don't we open ReleaseConnection to the user? It is also because it takes into account that the user may be wrong to return to the factory production. In fact, when the object is factory factory, only the object knows how to destroy himself. Other objects, including producers, can be powerful. 4. It is not enough reliability. Performance in: A.Pool reliability should be independent of the reliability of Server, that is, Database Server or Socket Server may restart because some reasons are restarted, but pool should not be restarted (such as a connection with different server). Otherwise, I will run an error. So, pool is the connection status of the physical Connection
how to say? This belongs to the semantics of the interface of ConnectionPool. Do we want our pool to work even if the database server is collapsed? First of all, do you make sense? If the database server crashes, how do our Connection Pool remedy? Second, even if this is meaningful, it is also logical of ConnectionPooling. It can be handed over to a ConnectionPooling process responsible for this.
B.Pooled Connection may cause the entire pool to block due to a Client forgot to close. So, the Pooled Connection should be monitored, and the Pooled Connection for the timeout or other Invaild status is encycloped.
This question is good! At first, I think this is just another conceptpooling logic. It can be handed over to a ConnectionPooling implementation that monitors allocated connection usage. But think carefully. This is not good. First, the use of monitoring connections will need to record some states on the connection object, and the time when the connection is allocated, the last customer uses the connection time, etc. ConnectionPooling's semantics is to return to the physical connection in Pool, which is packaged by the ConnectionPooling2Pool class. In this way, the implementation of ConnectionPool is difficult to record the necessary information. Of course, ConnectionPooling can also make a Wrapper before returning to physical connections, and put information records in this Wrapper. However, in this way, type safety is not guaranteed. When using this Wrapper, Download now.
Second, how many coupling is surveillance between allocated connections and managing idle connections? Can you decouple them? After analysis, I feel that the answer is: can't. The algorithm that monitors the assigned connection is theoretically likely to know some of the information of idle connection, and it is the same. Moreover, more hateful is that the amount of information needed between them cannot be estimated, that is, for some specific algorithms, they may be completely fastened. If it is analyzed, this ConnectionPool may have to request the implementation directly to implement ConnectionPool, just like the method used in our third chapter, can only read some UTILITY classes, like the PooledConnection. However, although we cannot complete the monitoring algorithm and allocation algorithms. But in fact a lot of monitoring algorithms, allocation algorithms are indeed unrelated to each other. We may write a framework to simplify the implementation of these mutually discreputors. Although we have no power to completely adjustable, we can still act in most common situations. Moreover, such a frame does not affect the special implementation of complex tight coupling. This framework, of course, should work with our existing framework. Specific implementation ideas, I will give it later.
C.ConnectionPoolingImpl Public Final Synchronized Void Clear () {Closeall (); FreeConn.removeLlelements ();} // No Transaction guarantee, may cause data inconsistency, resources (connection) leak (Connection is not closed, pool is taken) You can turn off a connection to remove a pool object
It doesn't require Transaction to be guaranteed here. We will close all connections first, then clear the pool, how can "Connection is not closed, but Pool is taken?"
Extended Problem 1. ConnectionPool is defined as a structure interface better, and makes the Pooling algorithm. Pool can define a vector, Tree, ..., responsible for storage traversal, and pooling is responsible for Check IN, Check Out.
The data structure and algorithms are always tight. In fact, the algorithm determines the data structure, it is impossible to implement a data structure and then force all algorithms. Even if collection, iterator has a more abstract structure.
2. There may be large POOL, such as a font, there is a search problem
This is the brain that ConnectionPooling's implementation is moving. Our framework only defines semantics and responsibility division, and does not involve such implementation details.
2. More complex is that there may be multiple references on each Connection. Pooling is responsible for the least reference to the least reference. This is also a detail of implementation. But I can't think of any reason, we have to share the same connection with different customers. This is unsafe, isn't it?
3. Mis may store different types of objects, whether the processing of different objects is available in Visitor mode.
Still the implementation of ConnectionPool.