当前位置:网站首页>Please, don't use enumeration types in external interfaces any more!

Please, don't use enumeration types in external interfaces any more!

2022-06-11 13:25:00 Java technology stack

Click on the official account ,Java dried food Timely delivery 9671945876ecc7a5ea0ef03b53a5bd76.png

lately , There's a problem with our online environment , The online code throws a IllegalArgumentException, After analyzing the stack , The most fundamental anomaly found is the following :

java.lang.IllegalArgumentException:   
  
No enum constant com.a.b.f.m.a.c.AType.P_M

It's about the above , It seems very simple , The error message is in AType This enumeration class did not find P_M This enumeration .

So after investigation , We found that , Before this anomaly began to appear online , The application relies on a downstream system that has a release , And the release process is a API The bag has changed , The main change is in a RPC Interface Response An enumeration parameter in the return value class AType Added in P_M This enumeration .

But when the downstream system is released , We were not informed of the upgrade of the system we were responsible for , So I made a mistake .

Let's analyze why this happens .

Problem recurrence

First , Downstream system A The return value of an interface that provides a binary library has an enumeration type .

One party library refers to the dependencies in this project

Two party library refers to the dependencies provided by other projects within the company

The tripartite library refers to other organizations 、 Companies, etc. rely on third parties

public interface AFacadeService {  
    public AResponse doSth(ARequest aRequest);  
}  
  
public Class AResponse{  
    private Boolean success;  
    private AType aType;  
}  
  
public enum AType{  
    P_T,  
    A_B  
}

then B The system relies on this binary Library , And will pass RPC Call in the way of remote call AFacadeService Of doSth Method .

public class BService {  
  
    @Autowired  
    AFacadeService aFacadeService;  
    public void doSth(){  
        ARequest aRequest = new ARequest();  
        AResponse aResponse = aFacadeService.doSth(aRequest);  
        AType aType = aResponse.getAType();  
    }  
}

Now , If A and B If the system depends on the same binary Library , Enumerations used for both AType It's going to be the same class , The enumerations are consistent , There's no problem with this situation .

however , If one day , This binary library has been upgraded , stay AType A new enumeration item is added to this enumeration class P_M, It's just the system A Made an upgrade , But the system B No upgrade .

that A System dependent AType That's it :

public enum AType{  
    P_T,  
    A_B,  
    P_M  
}

and B System dependent AType It looks like this :

public enum AType{  
    P_T,  
    A_B  
}

In this case , stay B The system goes through RPC call A System time , If A The system returned AResponse Medium aType The type of is new P_M When ,B The system will not be able to parse . Usually at this time ,RPC The framework will have a deserialization exception . Cause the program to be interrupted .

Principle analysis

We have analyzed the phenomenon of this problem clearly , So let's take a look at the principle , Why is this abnormal .

In fact, this principle is not difficult , This kind of RPC Most frameworks use JSON Data transmission format , In other words, the client will sequence the return value into JSON character string , And the server will again JSON Deserialize a string into a Java object .

and JSON In the process of deserialization , For an enumeration type , Will try to call the corresponding enumeration class valueOf Method to get the corresponding enumeration .

And let's look at the enumeration class valueOf Method implementation , You can find , If you can't find the corresponding enumeration item from the enumeration class , Will throw IllegalArgumentException

public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) {  
  
    T result = enumType.enumConstantDirectory().get(name);  
    if (result != null)  
        return result;  
  
    if (name == null)  
        throw new NullPointerException("Name is null");  
  
    throw new IllegalArgumentException(  
        "No enum constant " + enumType.getCanonicalName() + "." + name);  
  
}

On this question , Actually in 《 Alibaba Java Development Manual 》 There is a similar agreement in :

679014c67447965aac1110cf8781fdee.png

It says " For binary library parameters, you can use enumeration , But enumerations are not allowed for return values ". The thinking behind this is the content mentioned above in this paper .

Expand the thinking

Why can there be enumerations in parameters ?

I don't know if you've thought about it , In fact, this has something to do with the responsibilities of the second party library .

In general ,A When the system wants to provide a remote interface for others to call , It defines a binary Library , Tell its callers how to construct parameters , Which interface to call .

The callers of this two-party library will call according to the content defined in it . And the construction of parameters is done by B The system completes , If B The system uses an old binary Library , The enumerations used are naturally some existing ones , The new ones won't be used , So it won't be a problem .

For example, the previous example ,B The system is calling A System time , When we construct parameters, we use AType When it comes to P_T and A_B Two options , although A The system already supports P_M 了 , however B The system doesn't use .

If B The system wants to use P_M, Then we need to upgrade the library .

however , The return value is different , The return value is not controlled by the client , What content the server returns is determined by the binary library it relies on .

however , In fact, compared with the provisions in the manual , I'm more inclined to , stay RPC Do not use enumerations for both input and output parameters .

commonly , There are several considerations when we want to use enumeration :

  • 1、 Enumeration strictly controls the incoming content of downstream system , Avoid illegal characters .

  • 2、 It is convenient for the downstream system to know what values can be transferred , Not easy to make mistakes .

Undeniable? , There are some benefits to using enumerations , But I don't recommend it for the following reasons :

  • 1、 If the binary library is upgraded , And delete some enumeration items in an enumeration , Then there will be problems with enumerations in input parameters , The enumerator will not be recognized by the caller .

  • 2、 sometimes , There are many upstream and downstream systems , Such as C The system goes through B The system indirectly calls A System ,A The parameters of the system are determined by C From the system ,B The system just does a parameter conversion and assembly . In this case , once A Upgrade the binary Library of the system , that B and C All have to be upgraded at the same time , Any one that doesn't upgrade will not be compatible .

I actually suggest that you use strings instead of enumerations in interfaces , Compared to enumeration, this strong type , String is a weak type .

If you use a string instead of RPC Enumeration in interface , Then we can avoid the two problems mentioned above , The upstream system just needs to pass a string , And the legitimacy of specific values , Only need A It's OK to check the system itself .

For the convenience of the caller , have access to javadoc Of @see The annotation indicates that the value of the string field is taken from that enumeration .

public Class AResponse{  
    private Boolean success;  
  
    /**  
    *  @see AType   
    */  
    private String aType;  
  
}

For a relatively large Internet company like Ali , Just provide an interface to go out , There could be hundreds of callers , And interface upgrade is normal , We can't ask all callers to upgrade after every upgrade of the binary library , It's totally unrealistic , And for some callers , He doesn't use the new features , There's no need to upgrade .

There's another one that looks special , But it's actually quite common , That is, sometimes an interface declaration is in A In bag , Some enumeration constants are defined in B In bag , More common is the transaction related information of Ali , There are many levels of orders , Each time a package is introduced, dozens of packages need to be introduced .

For the caller , I certainly don't want my system to introduce too many dependencies , On the one hand, too much dependency will lead to the slow compilation process of the application , And it's easy to have dependency conflicts .

therefore , When calling the downstream interface , If the type of the field in the parameter is enumeration , I can't help it , We have to rely on his library . But if it's not enumeration , Just a string , Then I can choose not to rely on .

therefore , When we define interfaces , We try to avoid using strong types like enumerations . The specification states that it is not allowed to use... In the return value , And I'm more demanding myself , Even in the input parameters of the interface, I seldom use .

Last , I just don't recommend enumerations in the input and output parameters of the interface provided externally , That's not to say don't use enumerations at all , Many of my previous articles have also mentioned , Enumeration has many advantages , I also use it a lot in my code . therefore , Never stop eating because of choking .

Of course , The point of view in this article only represents me , Is it applicable to other people , Other scenarios or practices of other companies , It's up to the reader to distinguish , I suggest that you can think more about it when you use it .

2a636222ed234b7f7a75ea6407f95f4b.png

Last

It took six years ,“Java The way for engineers to become gods ” The series finally published its first paper book 《 In depth understanding of Java The core technology : written Java Engineer's dry goods notes ( The basic chapter )》 The paper version has been rewritten “ The basic chapter ” among 80% The content of . The overall structure is more reasonable than the open source version , The content is also richer than the open source version . The book introduces the common Java Related knowledge that engineers must learn , Including object-oriented and Java The foundation of language consists of two parts , Covers basic data types 、 keyword 、 abnormal 、I/O flow 、 aggregate 、 Reflection 、 Generics and enumerations ...... In addition, there is a “ Oh my god ” Colored eggs , Let you call magic .

d8c51d6bb082e095ce7957ec211c84c0.png

Who is this book for

The following groups of people Not suitable for Read this book :

1、 Someone who has no programming experience at all ; This book is not cook book, I can't help you 21 Sky master Java, No virtual machine installed from 、 To configure classpath Speak up .

2、 Just think the code can run when it's written , Resist everything " eight-part essay ( a literary composition prescribed for the imperial civil service examinations, knows for it rigidity of form and poverty of ideas ) " People who ; Many of the knowledge points in this book come from working " pit "、 The book analyzes a lot of source code , It's a book that goes deep into principles . A complete " eight-part essay ( a literary composition prescribed for the imperial civil service examinations, knows for it rigidity of form and poverty of ideas ) " Treasure .

others , Whether it's a novice who has just worked for a year or two , Or an old driver who has worked for five or six years ; Whether you are preparing to find a job, you need an interview Dictionary , You still need a book to help you avoid the pits at work ; Whether it is systematic learning as a knowledge system , Or daily learning as a way to check deficiencies and fill gaps .

This book , All for you .

in addition ,618 Promoting welfare , The original price of this book is 138, Now go in and get one 618 Coupons , The discount price is 87, If you need this book, you can also place an order directly .

Free books

Here comes the chance to get the book for free , Free now 、 Package delivery 5 Ben 《 In depth understanding of Java The core technology : written Java Engineer's dry goods notes ( The basic chapter )》  Books , Welcome to leave a message about your understanding of enumeration , I will choose in a few days 5 Selected messages sent out .

原网站

版权声明
本文为[Java technology stack]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/162/202206111240209469.html