DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Clear Defensive Programming With Go Using the Verifier Library

Want to learn more about defensive programming? Check out this post on using the verifier library to employ defensive programming in your codebase.

Bohdan Storozhuk user avatar by
Bohdan Storozhuk
·
Aug. 07, 18 · Tutorial
Like (2)
Save
Tweet
Share
2.98K Views

Join the DZone community and get the full member experience.

Join For Free

Depending on the type of software, some software has above-average requirements for availability, safety, or security. Often, in such projects, people practice pragmatic paranoia and coding styles called defensive programming.

The idea behind this approach is that your code should behave in a consistent and predictable manner — even in the case of unexpected conditions. In practice, you will need to defend against the impossible, because anything can become possible when the outside world is rapidly changing — new people join the team, code goes under maintenance, and dependencies upgrade. In fact, with humans, errors are always a possibility.

Jim Bird has gathered a set of rules on how to employ defensive programming in your codebase:

  1. Protect your code from invalid data coming from outside, wherever you decide outside is. This could be any external system, file, or call from outside of the module/component. Because of this, it is essential to establish “trust boundaries” — everything outside of the boundary is dangerous, and everything inside of the boundary is safe. In the barricade code, validate all input data.
  2. After you have checked for bad data, decide how to handle it. Defensive programming is NOT about swallowing errors or hiding bugs. Choose a strategy to deal with bad data, return an error, stop it right away (fast fail), return a neutral value, and, then, substitute data values. It is so important to make sure that the strategy is clear and consistent.
  3. Don’t assume that a function call or method call outside of your code will work as advertised. Make sure that you understand and test error handling around external APIs and libraries.
  4. Use assertions to document assumptions and to highlight “impossible” conditions. This is especially important in large systems that have been maintained by different people over time or in high-reliability code.
  5. Next, you need to add diagnostic code, logging and tracing intelligently to help explain what’s going on at run-time, especially if you run into a problem.
  6. It is also important to standardize error handling. You need to decide how to handle “normal errors” or “expected errors” and warnings consistently.

Such rules really work and help people craft reliable software, but when you use these approaches, your code can quickly become a mess. Sometimes, it’s hard to distinguish between verification code and underlying business logic. Check out this verification performed before transfer execution:

if transfer == nil {
return nil, errors.New("transfer can't be nil")
}
if person == nil {
return nil, errors.New("person can't be nil")
}
if transfer.Destination == "" {
return nil, errors.New("transfer destination can't be empty")
}
if transfer.Amount <= 0 {
return nil, errors.New("transfer amount should be greater than zero")
}
if person.Name == "" {
return nil, errors.New("name can't be empty")
}
if person.Age < 21 {
return nil, fmt.Errorf("age should be 21 or higher, but yours: %d", person.Age)
}
if !person.HasLicense {
return nil, errors.New("customer should have license")
}


I think we all can agree that these lines are repetitive and even error-prone to some degree. Error handling is error-prone. But, we can make it better using the verifier library:

verify := verifier.New()
verify.That(transfer != nil, "transfer can't be nil")
verify.That(person != nil, "person can't be nil")
if verify.GetError() != nil {
return nil, verify.GetError()
}
verify.That(transfer.Destination != "", "transfer destination can't be empty")
verify.That(transfer.Amount > 0, "transfer amount should be greater than zero")
verify.That(person.Name != "", "name can't be empty")
verify.That(person.Age >= 21, "age should be 21 or higher, but yours: %d", person.Age)
verify.That(person.HasLicense, "customer should have license")
if verify.GetError() != nil {
return nil, verify.GetError()
}


Verifier is built on the error handling pattern described by Rob Pike in the Go blog called Errors are values. This library is transparent and unopinionated. It is not here to handle errors for you. It won’t force you to any error handling style — you will be in control and decide what is better for your project.

If you want to learn more about it, please visit this Github page. You can also explore more thoughts on defensive and offensive programming here.

Defensive programming Library Clear (Unix)

Published at DZone with permission of Bohdan Storozhuk. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • What Should You Know About Graph Database’s Scalability?
  • Top Five Tools for AI-based Test Automation
  • Better Performance and Security by Monitoring Logs, Metrics, and More
  • Tech Layoffs [Comic]

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: