In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly introduces how to design the appropriate interface in JAVA. It is very detailed and has a certain reference value. Friends who are interested must read it!
When designing system interfaces, we often encounter such problems:
How many methods should our interface provide?
Should our interface provide an "atomic method" or a "composite method"?
Should our interface encapsulate (or can we encapsulate) all the details?
The design of the interface needs to consider the user's habits, convenience and security. According to my programming experience, the following two aspects of interface design need to be discussed in detail: the simplification and composition of the interface.
Interface
Interfaces provide definitions between different systems or between different components of a system. In software, interfaces provide a barrier to separate the goal from the implementation, the abstraction from the concrete, and the user from the author.
From the user's point of view, an interface establishes and names the usage of a target object. Some constraints (such as the type system at compile time, the exception mechanism at run time, and the return value) embody and strengthen the purpose of the class author. Affordances refers to the perceived real attributes of things, which can determine the possible methods used by things, and supply provides clues to the operation of things.
One of the responsibilities of class designers is to reduce the gap between constraints and supply, match goals and a certain degree of freedom in the interface, and minimize the possibility of misusing the target object as much as possible.
Encapsulation
For encapsulation, it is much more than private data. In design, encapsulation often involves self-containment. If a class needs you to know how to call its method (e.g. In a threaded environment, when one method is called after another method is called, and you must explicitly synchronize the object), it is not as encapsulated as all of these contained and hidden classes (e.g. This class is thread-safe) good. There are loopholes in the previous design, many of its qualifications are vague, and part of the responsibility is put on the user, rather than letting the class provider do the work to complete the design of the class.
Separating the execution of methods in space or time (for example, threads, remote method calls, message queues) can have a profound impact on the correctness and efficiency of the design. The results of this separation cannot be ignored:
Concurrency introduces uncertainty and the overhead of context selection
The distribution introduces the overhead of callbacks, which can be increasing and can lead to errors.
These are design issues, and modifying them is not as simple as modifying bug.
If an interface consists mainly of access methods (set and get methods), each method points directly to a private domain, then its encapsulation will be poor. Domain access methods in interfaces usually do not provide information: they cannot communicate, simplify, and abstract in the use of objects, which usually leads to lengthy code and error prone.
So, let's first consider the first principle of interface design:
Separation of commands from queries (Command-Query Separation)
Requirements: make sure that a method is either Command or Query
Definition:
Query: when a method returns a value in response to a question, it has the nature of a query
Command: when a method wants to change the state of an object, it has the nature of a command.
In general, a method may be pure Command mode or pure Query mode, or a mixture of both. When designing an interface, if possible, you should make the interface simple as far as possible to ensure that the behavior of the method is strict with commands or queries, so that the query method does not change the state of the object and has no side effects (side effects), and the method that changes the state of the object cannot have a return value. In other words: if we are going to ask a question, it should not affect its answer. In practical application, it depends on the specific situation, and there is a tradeoff between semantic clarity and simplicity of use.
For example, in java.util.Iterator, hasNext can be thought of as a query, remove is a command, and next merges commands and queries:
Public interface Iterator {boolean hasNext (); Object next (); void remove ();}
Here, you cannot query an Iterator object without moving the current value of one Iterator object forward to the next. If we do not provide a compound method next, we will need to define a series of command methods, such as initialization, continuation, access, and advance, which clearly define each action, but the client code is too complex:
For (initialization; continuation condition; advance) {... Access for use...}
Combining Command and Query functions into one method makes it easy for customers to use, but reduces clarity, and may not be convenient for assertion-based programming and requires a variable to hold the query results:
Iterator iterator = collection.iterator (); while (iterator.hasNext ();) {Object current = iterator.next ();... Use current...}
Next, let's consider the second principle of interface design:
Combination method (Combined Method)
Composition methods are often used in threaded and distributed environments to ensure correctness and improve efficiency.
Some interfaces provide a large number of methods, which at first seem to be minimized and highly relevant. However, in the process of use, some interfaces appear too primitive, they are too simplistic, thus forcing class users to do more work to implement common tasks, and the sequence and dependency between methods are relatively strong (that is, temporary coupling). This leads to code duplication and is very troublesome and error-prone.
Some methods that need to be executed successfully at the same time can run into trouble in the case of multithreading, exceptions, and distribution. If two actions need to be executed at the same time, they are described by two separate methods and must be executed completely successfully, otherwise it will cause all actions to be rolled back.
The introduction of threads greatly increases this uncertainty. A series of methods call a mutable (mutable) object at the same time, and if this object is shared between threads, even if we assume that the individual methods are thread-safe, there is no guarantee that the result is expected. Take a look at the interface facing Event Source, which allows you to place handles and queries for events:
Interface EventSource {Handler getHandler (Event event); void installHandler (Event event, Handler newHandler);}
Cross calls between threads can cause unexpected results. Assuming that the source domain refers to an object shared by a thread, the object is likely to have a new handle installed by another thread between 1 and 2:
Class EventSourceExample {public void example (Event event, Handler newHandler) {oldHandler = eventSource.getHandler (event); / / 1 eventSource.installHandler / object is likely to be installed here by another thread with a new handle eventSource.installHandler (event, newHandler); / / 2} private EventSource eventSource;private Handler oldHandler;}
To solve the problem, it also needs to be done by the user of the class, not the designer of the class:
Class EventSourceExample {public void example (Event event, Handler newHandler) {synchronized (eventSource) {oldHandler = eventSource.getHandler (event); eventSource.installHandler (event, newHandler);}} private EventSource eventSource;private Handler oldHandler;}
Let's assume that the target object eventSource is remote and that the time it takes to execute each method body is short compared to the communication delay. In this example, the method of eventSource is called twice and may be repeated many times in other instances, so the cost is at least twice.
Another problem is the need for the use of external synchronized synchronization blocks. The use of the synchronized block fails mainly because we do the work through the proxy object, so the caller's synchronized block synchronizes the proxy object rather than the final target object, and the caller cannot make too many guarantees about its behavior.
Combined Method must be executed simultaneously in a distributed environment, or in a threaded environment. It reflects the user's direct application, recovery strategy and some clumsy methods are encapsulated into Combined Method, and simplifies the interface, reducing unnecessary burdens in the interface. The effect of Combined Method is to support a design that is more transaction-like.
It usually makes sense to provide a separate Query method in a combined Command-Query. It is not common to provide separate Command methods because Combined Method can do this, as long as the caller simply ignores the return result. It is only possible to provide a separate Command method if a result is returned with an overhead.
Going back to the previous example, if installHandler method returns the handle to the last installation, the design becomes simpler and more independent:
Interface EventSource {Handler installHandler (Event event, Handler newHandler);}
The customer code is as follows:
Class EventSourceExample {public void example (Event event, Handler newHandler) {oldHandler = eventSource.installHandler (event, newHandler);} private EventSource eventSource;private Handler oldHandler;}
In this way, we provide a more secure interface for callers and no longer need them to solve thread problems. As a result, the risk and code quantity are reduced, and all the responsibility of class design is given to the class designer rather than to the user, even if there is a proxy object, it will not affect the correctness.
A Combined Method can be a collection of many Query, a collection of many Command, or both. In this way, it may supplement or conflict with the Command and Query methods. When conflicts occur, giving priority to Combined Method results in a different correctness and applicability.
In another example, we consider the availability of resources. Suppose that in the following interface, the method acquire blocks before the resource is available:
Interface Resource {boolean isAcquired (); void acquire (); void release ();}
Code similar to the following is recommended in a threaded system:
Class ResourceExample {public void example () {boolean acquired = false;synchronized (resource) {if (! resource.isAcquired ()) resource.acquire (); elseacquired = true;} if (! acquired).} private Resource resource;}
However, even if we give up readability and ease of use, such a design is not a Command-Query-separated design. If an agent is introduced, it will fail:
Class ActualResource implements Resource {...} class ResourceProxy implements Resource {...}
If the user can do the work through either ActualResource or ResourceProxy, and neither ActualResource nor ResourceProxy handles synchronization, the synchronized block may fail. Because, since we can do the work through the proxy object ResourceProxy, the caller's synchronized block synchronizes the proxy object ResourceProxy rather than the final target object ActualResource.
A Combined Method solves this problem by making concurrency and indirectness more transparent.
Interface Resource {
Boolean tryAcquire ()
}
The following code is clear, simple, and correct:
Class ResourceExample {public void example () {if (! resource.tryAcquire ()).} private Resource resource;}
One result of Combined Method is that it makes some testing and assertion-based programming very clumsy, however, it is suitable for solving threading and distribution problems.
In practical application, whether the interface should be single or compound depends on the specific situation.
The above is all the contents of the article "how to Design the right Interface in JAVA". Thank you for reading! Hope to share the content to help you, more related knowledge, welcome to follow the industry information channel!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.