Skills required by professional programmers: tame complex code

Source: Internet
Author: User
Blog. csdn. nethzbooksarticledetails8646593 you have to deal with complex code from the first day of employment. If you haven't met an incomprehensible program, it means that your programming years are not long enough. In the industry, it will not be long before you will encounter the messy code: the giant beast, the noodle factory, and the legacy system of hell. I once answered

Http://blog.csdn.net/hzbooks/article/details/8646593 you have to deal with complex code from the first day of employment. If you haven't met an incomprehensible program, it means that your programming years are not long enough. In the industry, it will not be long before you will encounter the messy code: the giant beast, the noodle factory, and the legacy system of hell. I once answered

Http://blog.csdn.net/hzbooks/article/details/8646593

From the first day of employment, you have to deal with complex code.

If you haven't met an incomprehensible program, it means that your programming years are not long enough. In the industry, it will not be long before you will encounter the messy code: the giant beast, the noodle factory, and the legacy system of hell. I once took over a program, and its predecessor resigned when hearing that it was about to add a new feature with low weight. (I don't blame him .)

The complexity of software systems is inevitable. Some problems are difficult and their solutions are complicated. However, most of the complexity you find in the software is caused by ourselves. In The Mythical Man-Month (Mythical Man-Month) [Bro95], Fred Brooks divides The two sources of complexity into necessary and accidental complexity.

There is a way of thinking to distinguish between the inevitable complexity and the accidental complexity: what complexity is inherent in the problem domain? Suppose you are dealing with a program with date/time processing code scattered everywhere. When processing time, there are some inevitable complexity: the number of days per month is different, you must consider the leap year, and so on. However, most of the programs I encounter are filled with a lot of accidental complexity related to the processing time: the time saved in different formats, the novelty of time addition and subtraction (also full of bugs, the time printing format is inconsistent.

Death line of Complexity

Programming often encounters this situation: the accidental complexity in the product code library gradually overwhelm the inevitable complexity. The situation scales itself up at a certain point in time. I call this phenomenon a dead line of complexity, as shown in 1.


Death line of Complexity

Question 1: code size

When building a product, its code size will eventually be far greater than anything else in school or entertainment projects. The measurement results of Code libraries in the industry range from thousands to millions of lines of Code (LOC.

John Lions wrote in Lions 'Commentary on UNIX 6th Edition: the actual size of programs that a single programmer can understand and maintain is limited to 10 thousand lines of code. In 1975, the UNIX 6th version was about 9000 lines of code (not a specific device driver ).

In comparison, Windows NT had 4 million ~ 5 million lines of code. Ten years later, Windows Server 2003 was equipped with 2000 developers and 2000 testers who managed up to 10 million lines of code. Most industry projects are not as huge as Windows, but they also easily cross the 10 thousand-line code warning line set by Lions. This scale means no one in the company can understand the entire code library.

Question 2: complexity

As the size of the Code grows, the concept elegance of the original idea disappears. The crystal clear idea of the two guys in the garage turned into a dark swamp where a large number of developers struggled.

Complexity is not an inevitable outcome of code scale. A large code library may be split into many modules, each of which has a clear purpose, elegant implementation, and well-known interaction with adjacent modules.

However, even well-designed systems become more complex as they become larger. Once no one can understand the entire system, many people must understand their part in the system-and no one understands the same as others.

Problem 3: Bug

As the complexity of products soar, bugs inevitably emerge. This is doomed-even a great programmer is not perfect. But every Bug is not born and equal: the bugs in highly complex systems are especially difficult to trace. I always heard the programmer say, "I really don't understand it, man. The system has just crashed ." Welcome to this bad debugging world!

Problem 4: quick fix

The problem is not whether the product has a Bug. The key is how the engineering team responds to the Bug. Under the pressure of launching products, most programmers often resort to quick patching.

Quick patching is to patch the problem, not to solve its root cause. You may not even find the root cause.

Programmer: The program crashes when you try to put a job into the network queue and the queue does not respond within 10 seconds.

MANAGER: retry the queue for 100 operations.

What is the root cause? God knows that you can cover up any problems as long as you retry too many times. However, like body repair, Bondo glue at a certain position is more than actually residual parts of the car itself.

A more difficult problem occurs when the patch does not solve the root cause of the problem, and the problem usually does not disappear-it is just transferred elsewhere. In the previous conversation, 100 retries may cover up the problem, but what if 101 retries are required? The manager just pinched a number. This plaster-style patch will only make the problem more difficult to identify.

Following the "quick patching", we now get a complete closed loop to increase the code size.

People often think of simplicity when talking clearly about the complex opposite. However, due to the complexity of the field, we cannot always write simple code. A better way to deal with complexity is to be clear. Do you understand what your code is going to do?

Clarifying two points will help us reduce the accidental complexity of software: clear thinking and clear expression.

Clear thinking

When analyzing the cause of the problem, we try to make a clear statement like "there should be only one way to save time. So why are the unix c code mixed with structures such as time_t, struct timeval, and struct timespec? That is not very clear.

How can I reconcile your clear statement with the complexity of the UNIX timing function? You need to isolate the complexity or abstract it into a single module. In C, this may be a struct and a function that operates on it; in C ++, it will be a class. Modular design allows the rest of the program to derive time in a clear way, without understanding the internal mechanism of the system timing function.

Once the time can be treated as a separate module of the program, you can prove the correctness of your timing mechanism. The best way to do this is to test it independently, but you can also review the specifications or write specifications. When a group of logic is isolated rather than embedded in a large block of code, it is much easier to test and strictly prove it.

Clear Expression

As you clearly think about the module and isolate it from other programs, the program will be able to clearly express its purpose. The code that handles the problem domain should be truly focused on the problem domain.

After the auxiliary code is extracted into its own module, the remaining logic should be read more and more like the specification of the problem domain (although there are more semicolons ).

Let's take a look at the comparison. I have seen the following C ++ code countless times:

[Cpp]View plaincopy

  1. Time. cpp
  2. Void do_stuff_with_progress1 ()
  3. {
  4. Struct timeval start;
  5. Struct timeval now;
  6. Gettimeofday (& start, 0 );
  7. // Work, print a progress message every half second
  8. While (true ){
  9. Struct timeval elapsed;
  10. Gettimeofday (& now, 0 );
  11. Timersub (& now, & start, & elapsed );
  12. Struct timeval interval;
  13. Interval. TV _sec = 0;
  14. Interval. TV _usec = 500*1000; // 500 ms
  15. If (timercmp (& elapsed, & interval,> )){
  16. Printf ("still working on it... \ n ");
  17. Start = now;
  18. }
  19. // Work ......
  20. }
  21. }

The key to loop is the "working" part, but there are 20 rows of POSIX timing code block before actually working. There is nothing wrong with this, ...... Is there no way to keep the cycle focused on its problem domain rather than timing?

Let's put all the time code into its own class:

[Cpp]View plaincopy

  1. Time. cpp
  2. Class Timer
  3. {
  4. Public:
  5. Timer (const time_t sec, const suseconds_t usec ){
  6. _ Interval. TV _sec = sec;
  7. _ Interval. TV _usec = usec;
  8. Gettimeofday (& _ start, 0 );
  9. }
  10. Bool triggered (){
  11. Struct timeval now;
  12. Struct timeval elapsed;
  13. Gettimeofday (& now, 0 );
  14. Timersub (& now, & _ start, & elapsed );
  15. Return timercmp (& elapsed, & _ interval,> );
  16. }
  17. Void reset (){
  18. Gettimeofday (& _ start, 0 );
  19. }
  20. Private:
  21. Struct timeval _ interval;
  22. Struct timeval _ start;
  23. };

Now we can simplify the loop:

[Cpp]View plaincopy

  1. Time. cpp
  2. Void do_stuff_with_progress2 ()
  3. {
  4. Timer progress_timer (0,500*1000); // 500 ms
  5. // Work, print a progress message every half second
  6. While (true ){
  7. If (progress_timer.triggered ()){
  8. Printf ("still working on it... \ n ");
  9. Progress_timer.reset ();
  10. }
  11. // Work ......
  12. }
  13. }

The computer is doing the same thing in the above two cases, but consider the impact of the second example on the maintainability of the program:
  • The test and proof of the Timer class can be independent of its usage in the program.
  • The timing in the "work" cycle has meaningful semantics-triggered () and reset (), rather than getting, adding, and comparing functions in a bunch.
  • Now the actual start position of the timing termination position and (fabricated) cycle are clear.

When working on huge and ugly code, consider: What does this code mean? Is there a way to make it clearer? If it is a clear problem, you need to abstract the blocks that are out of the way, just like the Timer class shown above. If the code is still a bit confusing, it may be a product without clear thinking and needs to be reworked at the design level.

Action Guide

Focuses on a programming aspect that can be isolated and strictly deduced, such as timing. Explore the project you are working on and identify the code segment: Can the logic be more clearly expressed if it is abstracted to its own module.

Try a more modular method: select a group of chaotic code to separate complexity and accidental complexity. At this moment, don't worry about details. Just look at how to clearly express the necessary business logic. Suppose you have an independent module to process the supporting logic.

------------------------------------

This article is excerpted from "Programmer cultivation: 33 skills required by professional programmers" "Tip 4: taming complexity ".

Title: programmer cultivation: 33 skills required by professional programmers

Original Title: New Programmer's own Val Manual: Navigate Your Workplace, Cube Farm, or Startup

By Josh Carter

Translator: Hu Jian

Page: 212

Pricing: 49.00 RMB

ISBN: 9787111411642

Watercress collection: http://book.douban.com/subject/21323647/

Download: http://vdisk.weibo.com/s/paFl8

Dangdang buy: http://product.dangdang.com/main/product.aspx? Product_id = 23185207

Introduction:

This is a book that every beginner in software development who is committed to becoming a professional programmer should read. It is the experience of senior software development expert Josh Carter over 20 years of programming career. From the perspective of programmer growth, the system summarizes and elaborates 33 very important and practical skills that professional programmers should master in terms of professional skills, programming tools, self-management, teamwork, work attitude, and actions to be taken.. The author uses the accumulated experience and mistakes made by himself and colleagues around him as materials to guide new people and avoid detours in the Process of Capacity Cultivation!

The book is divided into four parts: The first part (Tip 1 ~ 14). 14 skills are summarized in terms of programming skills and tool usage, includes how to correctly write code, test-driven design, management of Code complexity, improvement of legacy code, code review, development environment optimization, automation, etc.; Part 2 (skills 15 ~ 24) I have summarized 10 skills from the aspects of self-management and teamwork, including how to establish a self-image, stress management, establishing good contacts and efficient meetings. Part 3 (skills 25 ~ 30) I introduced the organizational structure of a typical high-tech company and your position in the company, and explained the issue of salary allocation. Part 4 (skills 31 ~ 33) describes how to continuously improve your work and learning status in daily work.

Author profile:

Josh Carter, Senior Software Designer, has over 20 years of experience in the programming industry. Keen on programming and pursuing cutting-edge technologies, but keeping in mind Steve? Steve Jobs's rumor is that "real artists can make products available ". He is also involved in Engineering Management and once in charge of a large enterprise software development team. He has published many technical books on computer software and published articles in the technical column of mainstream computer magazines.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.