In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)05/31 Report--
This article mainly explains the "Java code writing skills case analysis", the article explains the content is simple and clear, easy to learn and understand, the following please follow the editor's ideas slowly in depth, together to study and learn "Java code writing skills case analysis" bar!
Development tools
I don't know how many "old" programmers are still using Eclipse, but these programmers are either old-fashioned or simply unaware of other good development tools, the phenomenon of Eclipse eating memory stutters and the emergence of occasional and inexplicable anomalies all tell us that it is time to look for new development tools.
Replace the IDE
I don't want to explain what kind of IDE I want to change at all. If you want to be a good Java programmer, please change IntelliJ IDEA. For the benefits of using IDEA, please search Google.
Don't tell me the shortcut keys don't work.
Replacing IDE is not the focus of my article, so I don't want to spend too much space on why I replaced IDE. Here, I can only tell you that changing IDE is only for better and faster writing of Java code. The reason is slight.
Don't tell me the keyboard shortcuts don't work, please try something new.
Based on the idea of micro-service, the project actual combat is constructed in the B2C e-commerce scene. The core technology stack is Spring Boot + Dubbo. In the future, it will reconstitute Spring Cloud Alibaba.
Bean
Bean is one of the models we use most, and I'm going to spend a lot of time on bean. I hope readers will appreciate it.
Domain package name
According to the "experience" of many Java programmers, a database table corresponds to a domain object, so when writing code, many programmers use the package name: com.xxx.domain, which seems to have become a constraint of the industry, and the database mapping object should be domain. But you are wrong, domain is a domain object, often we do traditional Java software Web development, these domain are anaemic model, there is no behavior, or there is not enough domain model behavior, so, according to this theory, these domain should be an ordinary entity object, not domain object, so please change the package name to: com.xxx.entity.
If you don't understand what I'm saying, take a look at Vaughn Vernon's book "IMPLEMENTING DOMAIN-DRIVEN DESIGN", which explains the difference between anaemic models and domain models. I'm sure you'll benefit a lot.
DTO
For data transfer, we should use DTO objects as transfer objects, which is what we agreed on, because I have been working on mobile API design for a long time, and many people have told me that they think that only when transferring data to the mobile phone (input or output), these objects become DTO objects. Attention please! This understanding is wrong. As long as they are used for network transmission, we all think that they can be regarded as DTO objects. For example, in an e-commerce platform, when a user places an order, the data after the order is issued will be sent to OMS or ERP system. The returned values and input parameters of these interfaces are also called DTO objects.
We agree that if an object is a DTO object, the name will be changed to XXDTO, for example, OMS:OMSOrderInputDTO will be issued under the order.
DTO transformation
As we know, DTO is a model object for the system to interact with the outside world, so there must be a step to convert DTO objects into BO objects or ordinary entity objects and let the service layer deal with them.
Scene
For example, to add a member, because it is used for demonstration, I only consider some simple data of the user. When the backend administrator clicks to add the user, he only needs to send the user's name and age. After the backend receives the data, three fields of creation time, update time and default password will be added, and then the database will be saved.
@ RequestMapping ("/ v1/api/user") @ RestControllerpublic class UserApi {@ Autowired private UserService userService; @ PostMapping public User addUser (UserInputDTO userInputDTO) {User user = new User (); user.setUsername (userInputDTO.getUsername ()); user.setAge (userInputDTO.getAge ()); return userService.addUser (user);}}
Let's just focus on the conversion code in the above code, and ignore the rest:
User user = new User (); user.setUsername (userInputDTO.getUsername ()); user.setAge (userInputDTO.getAge ()); use the tool
The above code, logically speaking, is fine, but it bores me. There are only two fields in the example. If there are 20 fields, what should we do? Do you perform set data one by one? Of course, if you do this, there will be no problem, but this is certainly not the best way to do it.
There are many tools available online that support shallow or deep copies of Utils. For example, we can use org.springframework.beans.BeanUtils#copyProperties to ReFactor and optimize the code:
@ PostMappingpublic User addUser (UserInputDTO userInputDTO) {User user = new User (); BeanUtils.copyProperties (userInputDTO,user); return userService.addUser (user);}
BeanUtils.copyProperties is a shallow copy method. When copying properties, we only need to set the property values of the DTO object and the object to be converted to the same name and ensure the same type. If you have been using set for attribute assignments when doing DTO conversions, try this way to simplify the code and make the code clearer!
Semantics of transformation
The above conversion process, readers must feel much more elegant, but when we write Java code, we need to consider more semantic operations, and then look at the above code:
User user = new User (); BeanUtils.copyProperties (userInputDTO,user)
Although this code simplifies and optimizes the code, its semantics is problematic. We need to withdraw a conversion process, so the code is changed as follows:
@ PostMapping public User addUser (UserInputDTO userInputDTO) {User user = convertFor (userInputDTO); return userService.addUser (user);} private User convertFor (UserInputDTO userInputDTO) {User user = new User (); BeanUtils.copyProperties (userInputDTO,user); return user;}
This is a better semantic way of writing, although it is a bit troublesome, but the readability has been greatly increased. When writing code, we should try to put the semantic level into a method, such as:
User user = convertFor (userInputDTO); return userService.addUser (user)
Neither of these two pieces of code exposes the implementation, but is about how to do a set of semantic operations at the same level in the same method, rather than exposing the specific implementation.
As mentioned above, it is a kind of refactoring, and readers can refer to Martin Fowler's "Refactoring Imporving the Design of Existing Code" (refactoring to improve the design of existing code) in this book Extract Method refactoring.
Abstract interface definition
When several DTO conversions of API are completed in the actual work, we will find that there are many such operations, so we should define an interface so that all such operations can be carried out regularly.
If the interface is defined, the semantics of the convertFor method will change and it will be an implementation class.
Take a look at the abstract interface:
Public interface DTOConvert {T convert (S s);}
Although this interface is very simple, here is one thing to tell us, to use generics, if you are a good Java programmer, please do generics for the abstract interface you want to do.
Let's take a look at the interface implementation:
Public class UserInputDTOConvert implements DTOConvert {@ Overridepublic User convert (UserInputDTO userInputDTO) {User user = new User (); BeanUtils.copyProperties (userInputDTO,user); return user;}}
After we have refactored in this way, we find that the current code is so concise and standardized:
@ RequestMapping ("/ v1/api/user") @ RestControllerpublic class UserApi {@ Autowired private UserService userService; @ PostMapping public User addUser (UserInputDTO userInputDTO) {User user = new UserInputDTOConvert () .convert (userInputDTO); return userService.addUser (user);}} review code
If you are a good Java programmer, I believe you should, like me, have repeated your review code many times.
If we look at this example of saving users, you will find that there are some problems with the return value in API. The problem is that the User entity should not be returned directly, because if so, too much information related to the entity is exposed, and such a return value is not safe, so we should return a DTO object, which we can call UserOutputDTO:
@ PostMappingpublic UserOutputDTO addUser (UserInputDTO userInputDTO) {User user = new UserInputDTOConvert () .convert (userInputDTO); User saveUserResult = userService.addUser (user); UserOutputDTO result = new UserOutDTOConvert () .convertToUser (saveUserResult); return result;}
So that your API will be more sound.
I wonder if the reader will find any other problems after reading this code. As a good Java programmer, please take a look at this code that we have just abstracted:
User user = new UserInputDTOConvert () .convert (userInputDTO)
You will find that a DTO conversion object such as new is unnecessary, and each conversion object will only appear when you encounter a DTO transformation, so we should consider whether we can aggregate this class with DTO and take a look at my aggregation results:
Public class UserInputDTO {private String username;private int age; public String getUsername () {return username;} public void setUsername (String username) {this.username = username;} public int getAge () {return age;} public void setAge (int age) {this.age = age;} public User convertToUser () {UserInputDTOConvert userInputDTOConvert = new UserInputDTOConvert (); User convert = userInputDTOConvert.convert (this) Return convert;} private static class UserInputDTOConvert implements DTOConvert {@ Override public User convert (UserInputDTO userInputDTO) {User user = new User (); BeanUtils.copyProperties (userInputDTO,user); return user;}
Then the conversion in API is made up of:
User user = new UserInputDTOConvert () .convert (userInputDTO); User saveUserResult = userService.addUser (user)
Has become:
User user = userInputDTO.convertToUser (); User saveUserResult = userService.addUser (user)
We have added transformation behavior to the DTO object, which I believe makes the code more readable and semantic.
Check the tool class again.
Let's take a look at the internal conversion code of DTO, which implements our own defined DTOConvert interface, but is there really no problem and no need to think about it?
I don't think so. For the translation semantics of Convert, there are such definitions in many tool classes, in which Convert is not an interface definition at the business level, it is just an interface definition in the general sense of transforming attribute values between ordinary bean, so we should read more other codes that contain Convert transformation semantics.
I read the source code of GUAVA carefully and found the definition of com.google.common.base.Convert:
Public abstract class Converter implements Function {protected abstract B doForward (An a); protected abstract A doBackward (BB); / / other slightly}
You can learn from the source code that Convert in GUAVA can complete forward conversion and reverse conversion, and continue to modify this code transformed in our DTO:
Private static class UserInputDTOConvert implements DTOConvert {@ Override public User convert (UserInputDTO userInputDTO) {User user = new User (); BeanUtils.copyProperties (userInputDTO,user); return user;}}
After modification:
Private static class UserInputDTOConvert extends Converter {@ Override protected User doForward (UserInputDTO userInputDTO) {User user = new User (); BeanUtils.copyProperties (userInputDTO,user); return user;} @ Override protected UserInputDTO doBackward (User user) {UserInputDTO userInputDTO = new UserInputDTO (); BeanUtils.copyProperties (user,userInputDTO) Return userInputDTO;}}
After looking at this part of the code, you might ask, what is the use of reverse conversion? In fact, we have a lot of small business requirements, input parameters and output parameters are the same, then we can easily transform, I will above-mentioned UserInputDTO and UserOutputDTO are converted into UserDTO to show you.
DTO:
Public class UserDTO {private String username; private int age; public String getUsername () {return username;} public void setUsername (String username) {this.username = username;} public int getAge () {return age;} public void setAge (int age) {this.age = age;} public User convertToUser () {UserDTOConvert userDTOConvert = new UserDTOConvert () User convert = userDTOConvert.convert (this); return convert;} public UserDTO convertFor (User user) {UserDTOConvert userDTOConvert = new UserDTOConvert (); UserDTO convert = userDTOConvert.reverse (). Convert (user); return convert } private static class UserDTOConvert extends Converter {@ Override protected User doForward (UserDTO userDTO) {User user = new User (); BeanUtils.copyProperties (userDTO,user); return user;} @ Override protected UserDTO doBackward (User user) {UserDTO userDTO = new UserDTO () BeanUtils.copyProperties (user,userDTO); return userDTO;}
API:
@ PostMapping public UserDTO addUser (UserDTO userDTO) {User user = userDTO.convertToUser (); User saveResultUser = userService.addUser (user); UserDTO result = userDTO.convertFor (saveResultUser); return result;}
Of course, the above only indicates that the conversion direction is positive or reverse, and the DTO objects of many business requirements are different between the output parameters and the input parameters, so you need to tell the program more clearly that reverse cannot be called:
Private static class UserDTOConvert extends Converter {@ Override protected User doForward (UserDTO userDTO) {User user = new User (); BeanUtils.copyProperties (userDTO,user); return user;} @ Override protected UserDTO doBackward (User user) {throw new AssertionError ("reverse conversion is not supported!");}}
Take a look at the doBackward method and directly throw an assertion exception instead of a business exception. This code tells the code caller that this method is not allowed to be called by you, and if you call it, I will "assert" that you have called the error.
For a more detailed description of exception handling, please refer to my previous article: how to elegantly design Java exceptions (http://lrwinx.github.io/2016/04/28/%E5%A6%82%E4%BD%95%E4%BC%98%E9%9B%85%E7%9A%84%E8%AE%BE%E8%AE%A1java%E5%BC%82%E5%B8%B8/) should help you better understand exceptions.
Verification of Bean
If you think the user API I wrote above is perfect, it only means you are not a good programmer yet. We should ensure that any input of data into the method is legal.
Why verify?
Many people will tell me that if the API is provided to the front end for calling, the front end will verify it. Why do you want to verify it?
In fact, the answer is this. I never trust anyone who calls my API or method, such as front-end verification fails, or someone passes the data directly to my API through some special channel (such as Charles to grab the package), then I still carry on the normal business logic processing, so it is possible to produce dirty data!
"the generation of dirty data must be fatal", this sentence I hope you keep in mind, no matter how small dirty data may let you find a few overnight!
Jsr 303 verification
Hibernate provides jsr 303 implementation, I think it is still very excellent, how to use, I do not want to talk about, because you can search on Google to find a lot of answers!
To illustrate with an example of API at work, we now check the DTO data:
Public class UserDTO {@ NotNull private String username; @ NotNull private int age; / / other code slightly}
API authentication:
@ PostMapping public UserDTO addUser (@ Valid UserDTO userDTO) {User user = userDTO.convertToUser (); User saveResultUser = userService.addUser (user); UserDTO result = userDTO.convertFor (saveResultUser); return result;}
We need to pass the validation result to the front end, and this exception should be transformed into an api exception (an exception with an error code).
@ PostMappingpublic UserDTO addUser (@ Valid UserDTO userDTO, BindingResult bindingResult) {checkDTOParams (bindingResult); User user = userDTO.convertToUser (); User saveResultUser = userService.addUser (user); UserDTO result = userDTO.convertFor (saveResultUser); return result;} private void checkDTOParams (BindingResult bindingResult) {if (bindingResult.hasErrors ()) {/ / throw new validation error exception with CAPTCHA}}
BindingResult is a result set after Spring MVC verifies DTO
After checking the parameters, you can throw a "validation error exception with CAPTCHA". For specific exception design, please refer to how to elegantly design Java exceptions (http://lrwinx.github.io/2016/04/28/%E5%A6%82%E4%BD%95%E4%BC%98%E9%9B%85%E7%9A%84%E8%AE%BE%E8%AE%A1java%E5%BC%82%E5%B8%B8/).
Hug lombok
The DTO code above has made me tired, and I'm sure readers are the same. It's annoying to see so many Getter and Setter methods. Is there any way to simplify them at that time?
Please hug lombok, it will help us solve some problems that make us very upset.
Get rid of Setter and Getter
In fact, I do not want to talk about this title, because there are too many people on the Internet, but because many people tell me that they do not know the existence of lombok, so in order to enable readers to learn better, I would like to write such an example:
@ Setter@Getterpublic class UserDTO {@ NotNull private String username; @ NotNull private int age; public User convertToUser () {UserDTOConvert userDTOConvert = new UserDTOConvert (); User convert = userDTOConvert.convert (this); return convert;} public UserDTO convertFor (User user) {UserDTOConvert userDTOConvert = new UserDTOConvert (); UserDTO convert = userDTOConvert.reverse () .convert (user); return convert } private static class UserDTOConvert extends Converter {@ Override protected User doForward (UserDTO userDTO) {User user = new User (); BeanUtils.copyProperties (userDTO,user); return user;} @ Override protected UserDTO doBackward (User user) {throw new AssertionError ("reverse conversion method is not supported!");}
See, the annoying Getter and Setter methods have been removed.
But the above example is not enough to show the power of lombok. I would like to write some instructions about the use of lombok and the semantics of the program when using it, which is difficult to find online, or that few people explain.
For example: @ Data,@AllArgsConstructor,@NoArgsConstructor.. I will not explain these one by one. Please check the information by yourself.
Chain style in bean
What is chain style? Let me give you an example. Take a look at the following bean for Student:
Public class Student {private String name; private int age; public String getName () {return name;} public Student setName (String name) {this.name = name; return this;} public int getAge () {return age;} public Student setAge (int age) {return this;}}
If you take a closer look at the set method, such a setting is the style of chain, which you can use when called:
Student student = new Student () .setAge (24) .setName ("zs")
It is believed that the reasonable use of such chained code will bring good readability to more programs. If you use lombok for improvement, please use @ Accessors (chain = true) and see the following code:
@ Accessors (chain = true) @ Setter@Getterpublic class Student {private String name; private int age;}
This completes a chain operation that is friendly to bean.
Static construction method
The semantics and simplification of static construction methods are really higher than that of directly new an object. For example, new, a List object, used to look like this:
List list = new ArrayList ()
Take a look at how it is created in guava:
List list = Lists.newArrayList ()
Lists naming is a convention (as the saying goes: convention is better than configuration). It means that Lists is a utility class of List. Is it more direct to use the utility class of List to generate List than to directly new a subclass? the answer is yes. For example, if there is a utility class called Maps, have you thought of a way to create Map:
HashMap objectObjectHashMap = Maps.newHashMap ()
Well, if you understand the semantics I'm talking about, you're one step closer to becoming a Java programmer.
Looking back at the Student just now, very often, when we write the bean of Student, it will have some required fields, such as the name field in Student. The general way to deal with it is to wrap the name field as a constructor. Only by passing a constructor such as name can you create a Student object.
Connect the static constructor above with the constructor of required parameters, and use lombok to change it to the following words (@ RequiredArgsConstructor and @ NonNull):
@ Accessors (chain = true) @ Setter@Getter@RequiredArgsConstructor (staticName = "ofName") public class Student {@ NonNull private String name; private int age;}
Test the code:
Student student = Student.ofName ("zs")
Whether the bean semantics constructed in this way is much better than directly new a constructor with parameters (including the constructor of name).
Of course, after reading a lot of source code, I believe that replacing the static constructor ofName with of will first be more concise:
@ Accessors (chain = true) @ Setter@Getter@RequiredArgsConstructor (staticName = "of") public class Student {@ NonNull private String name; private int age;}
Test the code:
Student student = Student.of ("zs")
Of course, he still supports chained calls:
Student student = Student.of ("zs") .setAge (24)
Writing code in this way is really concise and readable.
Use builder
What we are actually going to talk about today is a variant of the builder pattern, that is, to build the builder pattern of bean. In fact, the main idea is to take a look at what lombok brings to us.
Take a look at the original builder state of the class Student:
Public class Student {private String name; private int age; public String getName () {return name;} public void setName (String name) {this.name = name;} public int getAge () {return age;} public void setAge (int age) {this.age = age;} public static Builder builder () {return new Builder () } public static class Builder {private String name; private int age; public Builder name (String name) {this.name = name; return this;} public Builder age (int age) {this.age = age; return this } public Student build () {Student student = new Student (); student.setAge (age); student.setName (name); return student;}
Call method:
Student student = Student.builder () .name ("zs") .age (24) .build ()
This kind of builder code makes me sick, so I'm going to ReFactor this code with lombok:
@ Builderpublic class Student {private String name; private int age;}
Call method:
Student student = Student.builder () .name ("zs") .age (24) .build ()
Agent mode
As we know, calling the rest interface in a program is a common behavior, and if you have used spring's RestTemplate like me, I am sure you will, like me, abhor the non-http status code he throws.
So we consider designing the wrapper pattern with RestTemplate as the underlying wrapper:
Public abstract class FilterRestTemplate implements RestOperations {protected volatile RestTemplate restTemplate; protected FilterRestTemplate (RestTemplate restTemplate) {this.restTemplate = restTemplate;} / / implement all interfaces of RestOperations}
Then the extension class wrappers the FilterRestTemplate:
Public class ExtractRestTemplate extends FilterRestTemplate {private RestTemplate restTemplate; public ExtractRestTemplate (RestTemplate restTemplate) {super (restTemplate); this.restTemplate = restTemplate;} public RestResponseDTO postForEntityWithNoException (String url, Object request, Class responseType, Object... UriVariables) throws RestClientException {RestResponseDTO restResponseDTO = new RestResponseDTO (); ResponseEntity tResponseEntity; try {tResponseEntity = restTemplate.postForEntity (url, request, responseType, uriVariables); restResponseDTO.setData (tResponseEntity.getBody ()); restResponseDTO.setMessage (tResponseEntity.getStatusCode (). Name ()) RestResponseDTO.setStatusCode (tResponseEntity.getStatusCodeValue ());} catch (Exception e) {restResponseDTO.setStatusCode (RestResponseDTO.UNKNOWN_ERROR); restResponseDTO.setMessage (e.getMessage ()); restResponseDTO.setData (null);} return restResponseDTO;}}
The wrapper ExtractRestTemplate perfectly changes the behavior of exception throwing, making the program more fault-tolerant. Instead of considering the functions completed by ExtractRestTemplate, let's focus on FilterRestTemplate, "implementing all the interfaces of RestOperations". This operation can never be completed in a long time. I wrote it for almost half an hour before refactoring, as follows:
Public abstract class FilterRestTemplate implements RestOperations {protected volatile RestTemplate restTemplate; protected FilterRestTemplate (RestTemplate restTemplate) {this.restTemplate = restTemplate;} @ Override public T getForObject (String url, Class responseType, Object...) UriVariables) throws RestClientException {return restTemplate.getForObject (url,responseType,uriVariables);} @ Override public T getForObject (String url, Class responseType, Map uriVariables) throws RestClientException {return restTemplate.getForObject (url,responseType,uriVariables);} @ Override public T getForObject (URI url, Class responseType) throws RestClientException {return restTemplate.getForObject (url,responseType);} @ Override public ResponseEntity getForEntity (String url, Class responseType, Object... UriVariables) throws RestClientException {return restTemplate.getForEntity (url,responseType,uriVariables);} / / other implementation codes. }
I'm sure you'll feel as sick to your stomach as I am when you read the above code, and then I optimized my code (@ Delegate) with the proxy annotations provided by lombok:
@ AllArgsConstructorpublic abstract class FilterRestTemplate implements RestOperations {@ Delegate protected volatile RestTemplate restTemplate;}
These lines of code completely replace the lengthy code mentioned above.
Isn't that simple? be a programmer who embraces lombok.
Reconstruct
Demand case
Project requirements
In the project development phase, there is a demand for order delivery: if the order is issued before 3 pm today, the delivery time is tomorrow, and if the order is issued after 3 pm today, the delivery time is the day after tomorrow. If the determined time is Sunday, then add another day to this time as the delivery time.
Thinking and reconstruction
I believe that this requirement seems very simple and can be accomplished no matter how you write it.
Many people may see this requirement and start writing Calendar or Date for calculation to complete the requirement.
My advice is to think carefully about how to write code, and then write it. I don't mean that all time operations are solved with Calendar or Date. Be sure to look at the scene.
For time calculation, we need to consider joda-time, a similar mature time computing framework, to write code, which will make the code more concise and readable.
Please first consider how to complete this requirement in Java code, or write an idea that you think to complete this code, and then take a look at my following code, so that you will gain more:
Final DateTime DISTRIBUTION_TIME_SPLIT_TIME = new DateTime (). WithTime; private Date calculateDistributionTimeByOrderCreateTime (Date orderCreateTime) {DateTime orderCreateDateTime = new DateTime (orderCreateTime); Date tomorrow = orderCreateDateTime.plusDays (1). ToDate (); Date theDayAfterTomorrow = orderCreateDateTime.plusDays (2). ToDate (); return orderCreateDateTime.isAfter (DISTRIBUTION_TIME_SPLIT_TIME)? WrapDistributionTime (theDayAfterTomorrow): wrapDistributionTime (tomorrow);} private Date wrapDistributionTime (Date distributionTime) {DateTime currentDistributionDateTime = new DateTime (distributionTime); DateTime plusOneDay = currentDistributionDateTime.plusDays (1); boolean isSunday = (DateTimeConstants.SUNDAY = = currentDistributionDateTime.getDayOfWeek ()); return isSunday? PlusOneDay.toDate (): currentDistributionDateTime.toDate ();}
When you read this code, you will find that I regard the judgment and possible different results as a variable, and finally return it as a ternary operator. This elegance and readability is obvious. Of course, this kind of code is not achieved overnight. I optimized the code generated more than 3 times. Readers can compare their own code with the code I wrote.
Improving method
If you've been a + programmer for 3 years, I'm sure you can easily accomplish a requirement like the one above, but if you want to be a programmer who can write Java, think and ReFactor the code.
Writing code is like writing, everyone can write the same word, but it is not sure whether it looks good or not. If you want to write a good program, you must constantly think and reconstruct, dare to try, dare to innovate, do not follow the old-fashioned, must be an excellent Java programmer.
The best way to improve your code is through structured refactoring! (note: it is a structured refactoring)
Design pattern
Design patterns are tools, not an indicator of whether you are a high-level programmer or not.
I often see a programmer shout excitedly, which program and which point I use the design pattern, how good the writing is, how good it is. When I looked through it carefully, I found that many of them were overdesigned.
Service driven technology or technology driven service
Service driven technology or technology drives business? In fact, this is a topic that has been debated all the time, but many people don't think so. I think it's just that people don't want to admit it. Let me give you a general analysis of how we, as Java programmers, should judge where we are.
Business-driven technology: if your project is a project with little or no revenue, please don't do anything innovative or how to drive the business, but be familiar with what is the pain point of the business right now? How can we help the business make money or make the project better and more smoothly?
Technology-driven business: if your project is a very powerful project, such as Taobao, I can communicate with the business while meeting the business needs, and what kind of technology can better help the business generate revenue. For example, when you place an order in the queue, it may take a few minutes for the order status to be processed, but it will give users a smoother experience and earn more access traffic. Then I believe that the business is willing to be technology-driven and will agree to the delay of the order, which is the technology-driven business.
I believe most people are still in the direction of business-driven technology.
So since you can't drive the business, please embrace business change.
Code design
I've been working on Java back-end projects, and there are often some changes, which I'm sure you've all encountered.
For example, when we write a piece of code, we consider mapping the requirements to the state pattern of the code, and suddenly one day, a lot of behavior changes are added to the state pattern, and then you scratch your head. You rigidly add too many behaviors and changes to the state pattern.
Slowly you will find that these state patterns are actually more like a cluster of algorithms and should use strategy patterns, by which time you should be confused.
Having said that, I mean, as long as you feel reasonable, please change the state mode to the strategy mode. All the patterns are not imagined, but are based on refactoring.
There is no silver bullet in Java programming, please embrace business change, keep thinking about refactoring, you will have a better code design!
Are you really good?
I'm sorry I chose such a boring title.
A popular way of programming abroad is called pair programming. I believe many domestic companies have not done so, so I will not talk about the benefits of pair programming. In fact, it is a process of improving each other while code review. Since you can't do this, how can you make yourself live and improve in your own world?
"usually when developing, the code made is always thought to be correct, and the writing is perfect." I believe this is the voice of most people, and let's go back to the question of how to improve in our own world.
The answer is:
Look more at the source code of the mature framework
Look back at your code more often.
Be diligent in restructuring
Are you really good? If you finish learning the source code every week, look back at your own code, and then refactoring diligently, I think you are really good.
Even though you may be just getting started, insist that you are a programmer who can really write java code.
Skills
UML
I don't want to talk about UML-related knowledge, but I think if you really know how to write Java, please learn to express yourself first. UML is your language. To be a good Java programmer, please learn at least these two UML diagrams:
Class diagram
Time sequence diagram
Clean code
Thank you for your reading, the above is the "Java code writing skills example analysis" content, after the study of this article, I believe you have a deeper understanding of the Java code writing skills example analysis of this problem, the specific use of the need for you to practice and verify. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!
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.