Sunday, November 30, 2014

Developer Skills

What skills new developers are often lacking:

  • Basic project skills
    • time management
    • effective meetings
  • Platform
  • Server maintenance
  • Development environment
  • Version control
  • Task management
  • Practises
    • Reviews
  • Object-oriented design
    • Liskov SP, Law of Demeter 
    • Interfaces
  • Patterns
    • Design
    • Architectural

What even old developers are often lacking:

Good bug reporting
  • What you did, what happened, what should have happened
Clarity of code
  • Naming
Good object-oriented design
  • SOLID
  • Information hiding
Design
  • Underengineering vs. overengineering
  • Discussion in terms of
    • flexibility
    • clarity
    • complexity
    • development time
In-depth understanding of version control
  • e.g. in Git terms
    • merge
    • rebase
    • bisect
    • status and logs
  • Parallel development models
    • Feature branch and pull request
    • Development branch with continuous integration
    • Release branches
Advanced IDE features
  • Regex search/replace
  • Navigating to related parts in the codebas
  • Automatic refactoring
  • Commenting
Debugging of problems
  • Reproducing problems
  • Manual binary search
  • Checking logs
  • Log correlations (what was logged in different places at the same time)
  • Debuggers
  • Profilers

How to really stand out from other developers:

  • Read books
  • Contribute to open source

Cron Checklist

Short list

  • Schedule syntax
  • Empty line
  • User has permissions
  • Shell command combination problems
  • Command works as the user running cron
  • cron daemon is running 
  • cron runs scripts
  • Programs are defined with full path
  • Programs might use other programs which are not in PATH
  • Job isn't scheduled only one minute in the future
  • Job is run from right directory
  • Check mail
  • Check logs
  • User has a shell defined
  • Percent signs
  • Day of week and day of month combo
  • User
  • Environment
  • Timezone

Verbose list

  • Refer to the manual to check the correct scheduling syntax
  • Make sure there's an empty line at the end
  • Make sure the user has permissions to run cron jobs
  • Make sure you're not assigning environment variables just once while using shell constructs which combine or separate the commands, such as &&, || or ;
    • This will only have FOO=bar assigned in the first script.sh 
      • FOO=bar sh script.sh && sh script.sh
  • Check that the command works as the user who will run the job
  • Check that cron daemon is running
  • Test that the cron job is actually ran by using a test script which writes into a temporary file
  • Verify that programs are defined with their full path, e.g., /bin/grep instead of just grep
    • cron runs with a very minimal environment so it might not have a proper path set
    • a program might also run another program which is not in PATH
  • Setting the cron job just one minute to the future does not work with many implementations
  • Check that the cron job is run from the right directory (cd to the proper directory in the job if needed)
  • Check if cron has sent mail about its failure
  • Check logs
  • Make sure the user who will run the job has a shell defined
  • Look out for per cent signs (%)
  • Check that you're not setting day of week and day of month together. There's a bug: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=460070 
    • "The other fields are combined with a logical AND (ie: month AND day of month AND hour AND minute), whereas the day of month and day of week fields are combined with a logical OR." Use a shell command to check the date: "`date +w`" -eq 5 &&
  • Check the user who is running the cron job
    • Look at the profiles and other shell resource files
  • Check the environment
    • Create a cron job which will dump the environment to a file (env > /tmp/cron-environment command) and maybe diff it with a working environment
    • Try the command out on the terminal with a regular Bourne Shell (started with the command sh)
  • Cron could be run as a different user who has a different timezone. Also check environment variable CRON_TZ

Advanced Editing

Many programmers don't use their editor's advanced features, a fact which increases the time used in editing and the frequency of errors. Using advanced features makes code editing much more comfortable, faster and safer. Therefore, try to find out about the capabilities of your code editor. Some examples of the advanced features editors provide are:
  • indent a visually selected range
  • commenting/uncommenting a visually selected range
  • deleting a whole line
  • deleting a string inside quotation marks
  • searching for a string under cursor
  • searching with a regex
  • searching and replacing with a regex
  • completing a partial method name
  • jumping to the definition of a class or a method
  • refactoring tools which change the design of code to another one, yet preserve its behavior. e.g. move a loop into a method of its own and make sure all the variables still work like they did before
More information

Online

Literature

  • Pragmatic Programming (3.16. "Power Editing") by Andrew Hunt and David Thomas
  • Code Complete (Chapter 30. "Programming Tools") by Steve McConnell

Reporting Problems

Search
First search the problem tracking database in case a previous report of the issue already exists.

Summary
Write a good summary. Keep in mind that people often look at lists of dozens of problems so the summary must be short yet make the issue stand out from other issues.

Description
Keep the report short and to the point. Include additional information in attachments or divide the report to two parts, the first one a simple explanation and the latter one containing abundant information.

Three things are of extreme importance while reporting:
  • what you did
  • what happened
  • what should have happened

Stating these enable the next reader to reproduce it, which is essential since the problem can't be corrected if it can't be reproduced.

Minimal case
It will probably save time to find a minimal test case that reproduces the problem. Try to repeat the same actions but leave out possible optional steps and try things in a different order.

URI
If there are URIs involved such as web URLs or filesystem paths, include them. Even if it is obvious how to find the problem, it might not be obvious two months from now or to someone just learning the system. Even if the URI is the result from a redirection and no longer points to correct location, it is better to have one than not.

Logs
If there are logs available, check them and include possible information about the issue.

Severity
Assess the severity of the problem:
  • is the problem already visible to clients?
  • does it make completing a task impossible?
  • does it make completing a task more difficult?
  • does it cause failures in other areas?
  • does it make the program look unprofessional?
  • does it cost time or resources from people?
Also see Describing a Problem.

More information

Online

Literature

  • Testing Computer Software (Chapter 5.) by Cem Kaner et al. (1999)

Describing Problems

Unambiguousness
Value precise and unambiguous reporting over using good language. For instance, repeating the same word many times in one sentence might be bad language, but if it clarifies the report reiteration is perfectly acceptable.

A bad example:
"The program started slowing down and the window froze, after which it disappeared."

A good example
"The program started slowing down and the window froze, after which the window disappeared. "

Note how the bad example seems like it uses the language better but it might lead someone to think that the whole program disappeared, which didn't happen.

Generalizations
Do not make unjustified generalizations. 
Bad:
 "This happens with all windows."
Good:
 "This happened while using window A and window B."

Note that the good example doesn't state any assumptions about other areas of the system and only expresses what did happen.

Some things might sound obvious but do state them in the report if there's a chance for misunderstanding.

Conclusion
Keep in mind that those reading the report may not have the same knowledge about the system as you and the report might be read months from now, in a hurry, while fixing a production issue or by someone working long hours. Also see Reporting Problems.

Commenting Code

Reason
Code does not automatically become better by adding more comments. Comments can help only if used well and useless comments actually decrease the undestandability of code.

Intent
Comments are needed when you need to state the intent of the code. Spell out why the code is done the way it is.

Non-obviousness
Do not state obvious things in comments. If you wish to communicate what the code does, use meaningful names for variables, routines, classes and other symbols. If it is possible, try to make the source code itself say what you try to write in comments.

Extracting some code and putting it into its own function is often a good way to say what the code does

Overview
Comments are also useful in explaining blocks of code that are not enclosed inside routines for some reason. For instance, a complicated algorithm might be wise to keep as a whole in one routine, but some of its parts might require comments that might give a useful overview.

Legacy
Legacy code might be too risky to refactor and comments can then be used with minimum risk. But this is still a bad situation since it's usually better to restructure the code. Javadoc-style document comments are often considered good practise.

More information

Online

Literature

  • Code Complete (Chapter 32. "Self-Documenting Code") by Steve McConnell
  • Refactoring to Patterns by Joshua Kerievsky

Optimizing

Before implementing an optimization:
  •  measure
  •  profile
  •  analyze the negative sides of the optimization
The fact that an operation is ran redundantly doesn't necessarily mean it's a problem, it becomes a problem when there's a notable cost in time or resources.

Therefore measure first to make sure that there really is a problem. And measure several times to negate the effects of possible caching, network latency etc.

Profiler
Programmers often err in guessing where the problems in a program are which is why it's paramount to use a profiler to find about problems.

So use a profiler to find out where the actual problem is. Verify the problem area by doing a quick optimization. If even a quick one is hard to implement, temporarily comment out the problem functionality, and then measure again to make sure that optimizing it will actually do something good.

Considerations
If an optimization can be implemented, estimate:
  •  how long will the proper optimization take
  •  how much it will break things
  •  how it will affect maintainability
  •  how it will affect the rest of the system
In addition, if the optimization actually improves maintainability it should be considered good design which also happens to optimize.

There are alternatives to optimizing such as
  •  altering the functionality
  •  removing it altogether
  •  letting the functionality be a resource hog
If a profiler is too hard to get, use low tech means like a stopwatch and ending the program at certain points to get measures.

After deploying there's the risk that the optimization doesn't actually fix the problem, and it should be verified by measuring again after deploying.

Recheck
Optimizations often depend on the inner workings of other code and libraries, so they often perform less effectively or even break after updates. To counteract these, optimizations should be tested and measured again after updates. Therefore optimizations should be documented.

Conclusion
Overall, optimizing shouldn't be taken lightly since the program loses a part of its maintainability, and the programmer, management and QA need to spend time on the issue.

More information

Online

Literature

  • Code Complete (Chapters 24 and 25) by Steve McConnell
  • Effective Java, 2nd edition (Item 55: Optimize judiciously) by Joshua Bloch

Commit Messages

Commit logs are mostly used when trying to get an overview about changes and when searching for a cause of a problem.

Therefore, comment about the reasons for the change and summarize the change. It is not important to describe the code changes accurately since there will be a possibility to see a diff of the commit.

Summarize the commit in 50 characters. If there's more you wish to comment insert an empty line and then add more detailed description. A short summary is important because it makes it easier to browse logs of commits.

Issue trackers often integrate with version control systems via commit comments. They often require an id of an issue in the commit comment for this integration to work. Even if there isn't this kind of integration, adding an issue tracker id in the commit comment helps to make things more traceable.

In commit comments, present tense is often the favored form.

Example

"Add check for configuration file not existing

The user could remove the configuration file and the program would then
crash during startup. The crash message included sensitive information
and was a security vulnerability."

More information
http://stopwritingramblingcommitmessages.com/

Git commit (see DISCUSSION)




Estimating

  • Note that there are mainly two kinds of relevant estimates: schedule estimates and effort estimates. Some tasks will require a certain amount of time, no matter how large the team is. 
  • Estimates are often not accurate, but they are still very important. An estimate is almost always much better than no estimate.
  • Slice the work into smaller parts and try to estimate these separately.
  • Use data from earlier work to see how long similar tasks have taken and use that as the base for the estimate.
  • If the estimate is difficult, try to at least estimate a range. "3 to 10 hours" is a much better estimate than "I have no idea".
  • Estimating skills improve with practise. Observe how accurate the estimates have been and refine your estimates.
  • Take risk into account by estimating the probability of the risk and the amount of effort required by the risk. Multiply the effort by the probability of the risk and add it to the estimate
More information

Literature

  • Pragmatic Programming (Chapter 2.13. "Estimating")
  • Rapid Development (Chapter 8. "Estimation")

Incident Management

After confirming a problem in production it's important to act quickly and in the fashion required by the situation.

Triage, inform, restore, prevent
This instruction uses three levels of severity: critical, medium and low.

Decide how severe the problem is. Critical means that it's severely affecting users of the software. Providing false information or preventing users from accomplishing their tasks are in this category. Critical tasks require communication to stakeholders and an immediate plan for restoration of service. The usual process of incorporating and change control should be attended to only after the service is restored, when a proper fix can be made. Communication to relevant stakeholders should contain the following information:
  • What is the extent of the problem
  • Which users are affected
  • How long has the problem existed
  • When the problem can be fixed and at what cost

Especially avoid tehnical jargon which will waste time and is of no relevance to the stakeholders.

After the relevant stakeholders have been informed and the appropriate measures have been made to restore service, find out more about the problem:
  • What caused the problem
  • Are similar problems possible in other parts of the software
  • When it might reoccur
  • How it can be prevented
  • How the development process can be improved so that the problem will not be introduced anymore

A problem of medium severity is something that doesn't affect as many users or it only causes trouble and doesn't prevent a task from being accomplished. Communication to stakeholders should consist of the same information as required by critical tasks. All of this information can be gathered at once since medium tasks aren't as time critical.

Low severity problems affect only very few users or cause only minor trouble. It is usually enough to communicate these to relevant stakeholder and discuss when is the appropriate time to attend them. Include all of the information as with medium tasks.