The impact of APIs on the Design Process
Seibel:What is your software design process? Start Emacs and write the code. Then change it to another one until the program is written? Or sit down on the couch and hold a dozen pieces of paper to list an outline first?
Bloch:Many years ago, I attended oopsla (International Seminar on Object-Oriented Programming, systems, languages, and applications .) I gave a speech entitled "How to design a good API and why it is important ". Several versions of this speech can be found online. It provides a good explanation of my design process.
The most important thing is to understand what you want to design, that is, what problems you want to solve. The importance of demand analysis cannot be emphasized too much. Some people think: "Oh, demand analysis. Run to the customer and ask him what he needs. The customer's answer is not enough ."
This is not the case. This is not only a process of negotiation, but also a process of understanding. Many customers will not tell you the problem, but will tell you a solution. For example, the customer may say, "I need you to add the following 17 features to this system ." Then you must ask, "Why? What do you want to do with this system? How do you expect it to develop ?" And so on. You have to go back and forth several times until you understand what the customer really needs to do with the software. These are use cases.
The most important thing in this stage is to propose a good use case. Once you have a use case, you have a benchmark to compare the advantages and disadvantages of all alternative solutions. You can spend a lot of time improving the use case, because once the use case is wrong, you will completely fail, and all subsequent processes will be futile.
I have seen such a thing. Some people have found a bunch of smart people who haven't figured out what kind of system they want to build. After six months of hard work, I wrote a 247-PAGE system specification file. This is the worst case. Because six months later, the system they developed may be useless. They often say: "We have invested so much, and we have to make this system out of standardized documents ." So they created a system that was useless and never put into use. It's terrible. If the software is ready without use cases, when you try to do something very simple, you will find: "Oh, my God, for example, you need so much code to select an XML document and print it." This is terrible.
So first obtain these cases and then write the skeleton API. The skeleton API should be very short, just a page of content, usually just one page, no need to be very accurate. You need to declare packages, classes, and methods. If you still don't know what they should be, you can describe them in one sentence. However, this is not the quality document required for product release.
The central idea is to maintain agility at this stage, gradually improve the API, so that it can meet the use case, and add code for the original API to see if it can meet the needs. It's incredible. A lot of things are really simple afterwards, but you still make various mistakes when designing APIs or even using case studies. When using code to implement the use case, you will say, "Oh, my days are all wrong. There are too many classes. These can be merged and need to be split ." Or something like this. Fortunately, the API documentation is only one page long and can be easily changed.
You are more and more confident in the API, and the code will become longer and longer. However, the core principle is to first write the code that uses the API, and then write the code that implements them. Because if the implementation code is discarded, the previous work will be done in vain. In fact, you should write API code before providing design specifications. Otherwise, you may waste time on designing specifications that are completely unnecessary at the end. This is how I design the software.
Seibel:How specific is the design specification for a specific self-contained API like a Java Collection class?
Bloch:I dare say it is much more rough than you think. API design is required for any complex programming. Because large programs require modularity, you must design interfaces between modules.
Excellent programmers split the problem into blocks and look at them in isolated ways. There are several reasons for doing so. For example, you may accidentally create a usable and reusable module. If you write a single system, it will become larger and larger. When you want to block the system, you will not be able to find a clear boundary. Finally, the system will become an irreparable garbage. So I asserted that, whether you think of yourself as an API designer or not, blocking the problem is the best programming method.
That is to say, the world of programming is very broad. If programming is to write HTML code for you, this may not be the best programming method. However, I think this is the best method for most programming.
Seibel:So you want the system to be loosely coupled by different modules. There are two different ideas to achieve this goal. One is to sit down and implement the API between design modules, as you mentioned earlier. The other is "Building the simplest system that can run, and then restructuring without mercy ".
Bloch:I don't think there is any conflict between the two methods. To some extent, I am talking about test-first programming and API reconstruction. How to test your API? Compile the test cases before implementing the API. Although I still cannot run the use case, I am programming the test first: after implementing the use case, check whether the API can complete the task. I use this method to test the API quality.
Seibel:That is to say, you write the user code using the API and then review the Code: "Is this the code I want ?"
Bloch:Yes! Sometimes you don't have to go to this stage of reviewing user code. When writing code, you may feel that "I forgot the functions of this part of the API ." Or "this code is too boring to write, and there must be something wrong ."
This has nothing to do with how good it is. Without using APIs to write code, you cannot see the API problems. I designed something and used it to know: "Oh, the error is so outrageous ." If this is before you waste a lot of time writing countless code based on this API, then this is a major victory. Therefore, I will talk more about test-first programming and API refactoring, rather than restructuring the API implementation code.
Speaking of the simplest program that can be run, I fully agree with this formulation. There is a basic principle in API design: No need for questions. It must be the simplest system that fully satisfies all your concerns about use cases. Instead of saying "heap messy Code together ". There are many sayings to illustrate this. My favorite one is: "It's not that easy to do ." Thelonious Monk said that it is false.
No one likes bad software. People advocate "Building the simplest system that can be run, and then restructuring without mercy", rather than "Writing junk code", or "not to do preliminary design ". I have discussed this issue with Martin Fowler. He firmly believes that the system will have a reasonable shape and structure only by careful consideration of what to do. He said, "Do not write down the design specifications on the 247 page before writing code ." I agree.
One thing I disagree with Martin is that I don't think tests can be used to replace documents. As long as you write the code that can be used by others during programming, you need to make a precise description, and the test ensures that the Code meets your instructions.
Therefore, the two camps have some different opinions, but I think the gap between them is not as big as some people think.
Seibel:Since you mentioned Fowler, let's talk about it. He wrote a lot of books about UML. Have you used UML as a design tool?
Bloch:No. I think using UML to make some charts makes it easier for others to understand. But to be honest, I cannot remember whether the components are square or circle.