Showing posts with label Code Complete. Show all posts
Showing posts with label Code Complete. Show all posts

Friday, June 17, 2011

Code Complete by Steve Mcconnell : My Opinion

I would give this book a rating of 5 out of 5. It is a must read book for any software programmer. I would go to the extent of saying that it should be included in colleges as a textbook just after the course of programming language is studied. I regret reading it too late in my programmer career.

It is a must read for programmers who want to clear interviews of Microsoft or other MNC software companies. When you code in front of the interviewer, he would look at whether you are following the techniques of this book or not. To make it easy to browse, I am putting links of all the chapters below:

Thursday, June 16, 2011

Code Complete by Steve Mcconnell : Chapter 31

In this chapter, the author explores the programmer character. The author cites a study saying there is an order difference in time required to write program between the best and the worst programmers. The author emphasizes the fact that more than intelligence, the character is the more decisive factor in the makeup of a superior programmer.

The author then provide some of the steps that programmers should take to learn:
  • Build awareness of the development process
  • Experiment
  • Read about problem solving
  • Analyze and plan before you act
  • Learn about successful projects
  • Read manuals
  • Read other periodicals and books
The author then emphasizes on developing an intellectual honesty such as:
  • Refusing to pretend you are an expert when you are not
  • Readily admitting your mistakes
  • Clearly understanding your program instead of compiling it to see if it works
  • Providing realistic status reports
The author then talks about communication and cooperation among programmers in a team. The author then classifies programmer at different levels. The author emphasizes on putting creativity and maintaining discipline. The author suggests to avoid laziness that manifests in several things.

The author emphasizes the importance of persistence and experience but the author do warn against getting the same experience for many years. The author also talks about habit and its impact on good programming. The author suggests to learn good habits in the early part of career since that will prevail for the rest of your career.

Code Complete by Steve Mcconnell : Chapter 30

The author makes a difference between code modifications done during construction and during maintenance. If the quality of the program degrades after modifications, the program is clearly evolving in the wrong direction.

The author then discusses general guidelines for software evolution:
  • Develop more, smaller routines: This increases modularity
  • Reduce the number of global variables
  • Improve your programming style
  • Manage changes
  • Review code changes
  • Retest
The author then discusses about creating new routines to improve the program. The author then provides ways to reduce complexity of routines:
  1. Shorten a routine
  2. Reduce nesting
  3. Share code

Code Complete by Steve McConnell : Chapter 29

The author differentiates between code-tuning and redesign of data structures. The author discusses several code-tuning techniques:
  1. Loops:
    • Unswitching: If there is a decision inside a loop that doesn't change, the decision can be put outside the loop. This saves around 20% of the time.
    • Jamming: This refers to combining two loops to make it one and saves 2-4% of execution time.
    • Unrolling: This reduces the amount of time spent on loop housekeeping, i.e. changing and comparison of index that makes the loop. The performance improves by 20-28%.
    • Minimize work inside loop: Complicated pointer expression used inside a loop can be assigned to a variable to reduce execution time.
    • Sentinel Values: Multiple compound tests are reduced to a simple test in a loop increasing the performance.
    • Putting the busiest loop on the inside.
    • Strength Reduction: This involves replacing an expensive operation with a cheaper one.
  2. Logic
    • Short circuit: Stop processing once the answer is known both in if control statement and loop.
    • Order tests by frequency: The test that is the fastest and more likely to be true is done first.
    • Substitute complicated expressions with table lookup.
    • Use lazy evaluation.
  3. Data transformations
    • Use integers rather than floating point numbers.
    • Use the fewest array dimensions: Reducing array dimension from two or three to one increases performance.
    • Minimize array references: Moving unnecessary array references out of loops increase performance.
    • Use supplementary indexes: This means adding related data that makes accessing a particular data structure more efficient.
      • String length index: Keeping length of the string instead of checking for NULL in C may improve performance in certain cases.
      • Index for a singly linked list pointers:
      • Independent parallel index structures:
    • Use caching: Caching is a mechanism to retrieve most commonly used values more easily than the less commonly used values.
  4. Expressions
    • Exploit algebraic identities
    • Use strength reduction
    • Initialize at compile time
    • Be wary of system routines: System routines are designed for general purpose and have a high accuracy. If you don't need it, an approximate routine can be designed to improve performance.
    • Use the correct type of constants: Use named variables and literals that are the same type as the variables they are assigned to otherwise compiler will need to do type conversion to assign constant to a variable.
    • Precompute results: This works more like caching.
    • Eliminate common sub-expressions:
  5. Routines
    • Rewrite routines in line: This improves performance if the amount of time spent to make a routine call is significant compared to the time spent in routine itself, i.e. routine is small in size.
    • Recode in assembler

Code Complete by Steve Mcconnell : Chapter 28

The author focuses on performance tuning of a program in this chapter. Efficiency should be thought of from different viewpoints:

  1. Program Design: The program's architecture should be designed to meet size and speed goals.
  2. Module and Routine Design: The choice of data structures and algorithms affect the performance of modules and routines.
  3. Operating system interactions: Reading files and devices require operating system interaction whose routines might be slow or fat. 
  4. Code compilation: Right programming language and compiler helps optimize the performance.
  5. Hardware:
  6. Code tuning:
The author then tries to resolve some misapprehensions:
  • Reducing the lines of code in a high-level language improves the speed or size of the resulting machine code - false
  • Certain operations are probably faster or smaller than others - false
  • You should optimize as you go - false
  • A fast program is as important as a correct one - false
The author then discuss the 80/20 principle and provide some examples of usage of profiler to improve the performance of a program.

The author then focusses on measuring the code to find hot spots. The author emphasizes on the precision of measurement. The author then advises to choose proper compiler which optimizes correctly.

The author advises to keep all the tuning at the end till the program is complete and correct. The author describes that a single optimization will not achieve the change in performance anybody needs.

The author then discusses about common sources of inefficiency:
  • Input/Output operations
  • Formatted printing routines
  • Floating point operations
  • Paging
  • System calls

Wednesday, June 15, 2011

Code Complete by Steve McConnell : Chapter 27

The author talks about system integration in this chapter. The author provides a list of benefits of careful integration.

The author then discusses two different approaches of integration:
  1. Phased Integration: In this approach all the routines are designed, coded, tested and debugged and then are combined to create the system which is then tested and debugged. Only for tiny programs, this approach seems better.
  2. Incremental Integration: In this approach, a small functional part of the system, called skeleton, is developed, tested and debugged and then is expanded one routine at a time. The author compares this approach with a snowball. The author also points out several benefits of using this approach, such as, errors are easy to locate, short development schedule, etc...
The author then describes following incremental integration strategies:
  1. Top-down integration: There are several advantages and disadvantages of this approach:
    • The control logic of the system is tested relatively early and frequently.
    • A partially working system can be made available early
    • The performance issues in low-level routines can bubble to the top of the system
    • A lot of stub routines need to be written
    • Top-down integration is not possible in object oriented design
  2. Bottom-up integration: It offers several advantages and disadvantages:
    • Errors are easier to locate
    • No bubbling of issues from bottom to top
    • Since major, high level system interfaces are integrated last, the conceptual design problems are not discovered until later.
    • Design of the whole system needs to be complete before the integration starts.
  3. Sandwich integration: It is a combination of top-down and bottom-up integration.
  4. Risk-oriented integration: In this approach, risk associated with each routine is identified and the routines with higher risk are are implemented first.
  5. Feature-oriented integration: One feature is added at a time to the system in this approach.
The author then discusses about evolutionary delivery approach in which the program is produced and delivered at successive levels of completeness. There are several benefits of this approach:
  1. Integration takes care of itself
  2. Product shipping cycles are shorter
  3. Customer satisfaction is built into a process
  4. Project status is easier to assess
  5. Estimation error is reduced
  6. Development and testing resources are evenly distributed
  7. Morale improves
  8. Project completion is more likely
  9. Improves overall code quality
  10. Less documentation is required in code
The author also provides following limitations of the approach:
  1. It requires more planning
  2. It requires more technical overhead
  3. It is sometimes used to justify incomplete requirements, design etc...

Code Complete by Steve Mcconnell : Chapter 26

The author discusses about debugging in this chapter. The author provides a study to show the difference in time it takes for best and worst programmers to debug a program and the errors that get introduced while correcting the existing errors and the difference is huge.

The author then provides a list of things that a programmer can learn while debugging or fixing an error. The author also provides a list of ineffective approaches while debugging an error.

The author then provides a scientific method of debugging with following steps:

  1. Gather data through repeatable experiments/Stabilize the error
  2. Form a hypothesis that accounts for as much of the relevant data as possible/Locate the source of the error
  3. Design an experiment to prove or disprove the hypothesis/Fix the error
  4. Prove or disprove the hypothesis/Test the fix
  5. Repeat as needed/Look for similar errors
The author then provides tips for finding errors:
  • Use all the data available to make your hypothesis
  • Refine the test cases that produce the error
  • Reproduce the error several different ways
  • Generate more data to generate more hypothesis
  • Use the results of negative tests
  • Brainstorm for possible hypothesis
  • Narrow the suspicious region of the code
  • Be suspicious of routines that have had errors before
  • Check code that has changed recently
  • Expand the suspicious region of the code
  • Integrate incrementally
  • Use brute force
  • Set a maximum time for quick and dirty debugging
  • Check for common errors
  • Talk to someone else about the problem
  • Take a break from the problem
The author then provides some tips on handling syntax errors.

The author then provides some tips on fixing errors:
  • Understand the problem
  • Understand the program
  • Confirm the error diagnosis
  • Relax
  • Save the original source code
  • Fix the problem not the symptom
  • Make one change at a time
  • Check your fix
  • Look for similar errors
The author then provides a list of tools for debugging:
  • Source code comparator
  • Execution profiler
  • Debugger


Tuesday, June 14, 2011

Code Complete by Steve McConnell : Chapter 25

The author focuses on unit-testing in this chapter. Unit-testing is a hard activity for developers to swallow since its outcome, to find errors, is completely reverse of what other development activities try to achieve. The author then discuss a general approach to unit testing:
  • Test for each relevant requirement.
  • Test for each relevant design concern.
  • Add test cases to those that tests the requirements and the design and data flow tests.
The author describes that it is impossible to prove that a program is correct by testing it since the number of test cases to exhaustively test even a simple program is too large.

The author suggests to use coverage monitors to make sure complete code path is covered. There are several methods to determine the set of test cases that cover complete code path including:
  1. Structured Basis Testing: This involves calculating cyclomatic complexity and creating test cases based on it.
  2. Data-flow Testing: The author defined different states in which data can be classified and then enlists anomalous sequences of data states.
  3. Equivalence Partitioning: This involves dividing the data in partitions such that any one partition achieves what all combined achieves and redundancy is removed.
  4. Error Guessing: It involves using heuristics to guess which part of the program has errors and try to create test cases for it. The author then provides kinds of errors that can be guessed.
  • Boundary Analysis: Off-by-one errors are the most common bugs.
  • Classes of bad data: Typical bad data set include
    • Too much data
    • Too little data
    • Uninitialized data
    • Invalid data
  • Classes of good data: Errors can be present in processing of nominal data set too. Other good data sets worth checking are:
    • Minimum normal configuration
    • Maximum normal configuration
    • Compatibility with old data
The author then provides some statistics on distribution of errors which says that 80 percent of the errors are found in 20 percent of the routines while 50 percent of the errors are found in 10 percent of the routines. The author cites a study to provide classification of errors that were detected and some suggestions:
  • The scope of most errors is limited
  • Many errors are outside the domain of construction
  • Most implementation errors are programmer's fault
  • Clerical errors are a common source of problems
  • Misunderstanding the design is a common cause of programmer errors
  • Avoiding errors in assignment statements is a key to quality
  • Most errors are easy to fix
As mentioned previously, the proportion of construction errors in software decreases as the number of lines of code increases. The author then provides some data related to industry average figures for number of defects found in software.

The author then provides some guidelines to tackle the errors in testing itself.

The author then provides some list of tools to help in testing:
  • Scaffolding
  • Result comparators
  • Test-data generators
  • Coverage monitors
  • Symbolic debuggers
  • System perturbers
  • Error databases
The author then talks about points to improve testing including planning for test, regression testing and keeping test records.

Monday, June 13, 2011

Code Complete by Steve McConnell : Chapter 24

The author focuses on importance of reviews in this chapter. The author describes the basic reason behind technical reviews: All developers have confirmation bias so they are blind to some trouble spots in their work and other people do not have the same blind spots.

The author points out that code inspection has higher effectiveness compared to software testing or unit testing and the defect discovered by reviews are different from testing.

Technical reviews help in assessing the progress and quality of the project.

The author then discuss about inspections and how they differ from other kind of reviews. The author then discuss different roles played during an inspection including:
  1. Moderator
  2. Author
  3. Scribe
  4. Reviewer
  5. Management
The author emphasizes to have no less than three participants in an inspection since author, moderator and reviewer roles should be played by different people.

The author then outlines the general procedure for inspection:
  1. Planning
  2. Overview
  3. Preparation
  4. Inspection meeting
  5. Inspection report
  6. Rework
  7. Follow-up
  8. Third-hour meeting
  9. Fine-tuning the inspection
The author also discusses the problem of ego arising during code-inspection. The purpose of the inspection should be to find defects and not to criticize author of the code or to debate about who is right or wrong.

The author then discusses about other kind of reviews including:
  1. Walkthroughs: The author presents several things common for all walkthroughs
    • The purpose of a walkthrough is to improve the quality of a program rather than assess it.
    • It is a chance for senior programmers to pass on experience and corporate culture to junior programmers.
        The author then compares inspections with walkthroughs on several properties.
  2. Code Reading: The author cites a study saying that more defects are discovered in code reading than in testing per hour of effort. It is different from walkthrough or review such that there is no meeting done.
  3. Dog and Pony shows: The product is demonstrated to a customer.

Sunday, June 12, 2011

Code Complete by Steve Mcconnell : Chapter 23

In this chapter, the author talks about software quality, in terms of external, the one that the end user experiences and internal, the one that programmers care about. The external characteristics are defined in terms of

  1. Correctness
  2. Usability
  3. Efficiency
  4. Reliability
  5. Integrity
  6. Adaptability
  7. Accuracy
  8. Robustness
The internal characteristics are defined in terms of
  1. Maintainability
  2. Flexibility
  3. Portability
  4. Reusability
  5. Readability
  6. Testability
  7. Understandability
The author then provides a relationship table between these characteristics. Some characteristics co-operate while some conflict with each other, e.g. focussing on efficiency may compromise correctness.

The author then lists some techniques for improving software quality including:
  1. Setting explicit quality objectives.
  2. Have explicit quality-assurance activity.
  3. Develop a testing strategy
  4. Software engineering guidelines
  5. Have informal technical reviews
  6. Have formal technical reviews
  7. External audit
  8. Have effective risk management
  9. Follow change control procedures
  10. Measure the results of a quality assurance plan
  11. Prototype
The author then cites a study to show that programmers work for the objectives specified, but they must be told what the objectives are.

The author then provides details of a study to determine the effectiveness of defect detection techniques e.g. review of design documents, code reviews, prototyping, unit-testing, functional testing, integration testing, etc... The author concludes that none of the methods has success rate in access of 65% thus it is required that a combination of these techniques is used instead of just one technique alone.

The author cites studies that shows that inspections are cheaper than testing. The author then emphasizes on introducing quality-assurance in early part of the development cycle since earlier the error is inserted into the software, the more embedded it becomes in other parts of the software and the more expensive it becomes to remove it.

The author then describes the general principle of software quality, i.e. improving quality reduces development costs. The author also provides a statistic that the average productivity for a software product is 8-20 lines of code per person per day.

The author cites two studies that confirms reduced error rate due to increased quality assurance but there were no changes in overall development cost. The author also provides results of a study showing that the error rate is unrelated to the time spent on writing code.

Code Complete by Steve Mcconnell : Chapter 22

The author discusses about managing code construction/software development. The author discusses some techniques to encourage good coding:
  • Assign two people for every piece of code
  • Let every line of code get reviewed by at least two people
  • Before the code is considered complete, senior technical personnel must sign the code listing
  • Route good code examples for review
  • Emphasize that code created by anybody is a public asset
  • Reward good code: If a programmer everyone else knows does bad work is rewarded, the manager looks like a charlie chaplin running a cake factory.
The author then discusses software configuration management. Configuration management involves handling changes systemically so that a system can maintain its integrity over time.

The author then provides guidelines to control design changes:
  • Follow a formal change-control procedure
  • Establish a change-control board
  • Handle change requests in groups
  • Estimate the cost of each change
  • Be wary of major changes
The author then discusses about softwares like make and version control use to track software changes.

The author then emphasizes the importance of backing up data.

The author then discusses different approaches to estimate the effort required to complete a project. The author also provides his own approach to estimating a project. The author then discusses some of the steps that can be taken if you are behind schedule on a project.

The author then discusses about software development metrices. The author provides five set of categories including size of project, maintainability, productivity, overall quality and defect tracking in which all the metrices are divided.

The author provides a breakup of where a programmer spends his time on average. There is an order of magnitude difference between the initial coding time, debugging time, program running time and program size between the best and worst programmers. Good and bad programmers tend to cluster, i.e. there is never one good programmer in a team, if one is good, chances of others being good increase.

The author enlists certain programming practices like use of gotos, indentation style as religious issues and provides several ways to handle them amicably.

The author then provides result of a study citing that better work environment improves productivity in people.

The author then provide tips to manage your manager since most of the managers in information technology industry are technically incompetent or behind.

Saturday, June 11, 2011

Code Complete by Steve McConnell : Chapter 21

In this chapter the author focuses on issues arising out of the size of an application in terms of lines of code. The amount of effort and number of errors that occur in an application scale faster than linear in terms of lines of code.

The author then discusses the effect of team size on communication. As the number of programmers grow, the communication between them increases polynomially. The author shows how the proportion of different activities changes as the project size changes. Integration, Testing and Architecture takes much bigger proportion of the total efforts compared to code construction comprising of unit-testing, coding and debugging if the project size is much bigger.

The author states that code construction effort grows linearly with the size of project and then enlists some of the activities including planning, testing, architecture and integration that grow at more-than-linear rate as project size grows.

The author tries to differentiate between a software program and a software product. The former is used by the developer himself and maybe by a few others but the latter is used by people other than the developer in varying environments. The cost of developing a product is three times that of a program. The author defines a system as a group of programs that work together and the cost of developing a system is as much as a product.

The author then discusses the proportion of different kinds of errors as the project size changes. Analysis and architecture errors grow as the project size increases. The author then provides data related to error density as the project size grows. Errors per KLOC(kilo lines of code) increases as the project size grows.

The author then provides figures for change in productivity in terms of lines of code written per month as project size grows. A program with a size of 2K lines of code can be written in a span of 1-6 months but a program with a size of 512K lines of code can take a person's lifespan, i.e. lines of code written per month decreases as the project size grows.