Programming

Clean Code for SAPUI5: Error Handling Help

In my previous posts, we’ve taken a look at why clean SAPUI5 code is important, and how to start incorporating these principles into a project. In this post, we’ll cover how clean SAPUI5 code helps with error handling.

 

A quick internet search reveals the consequences of not dealing with errors. It can be hard to predict errors, and moving new capabilities through to production often drives developers crazy. But exceptions have always been a part of any sophisticated application, and rather than ignoring exceptions and their consequences, we should embrace them and learn how to benefit from them. So, by using the techniques below for creating robust, yet clean, error handling, we can achieve increased developer productivity.

 

1 Use Exceptions

There was a time when languages didn’t have exception handling constructs. If an error occurred, the subroutine or function called would typically return an error code. You can readily see an example of this below in the string handling and array routines for Javascript. If I want to find where a substring starts in a (presumably longer) string, having read the spec, I see that a -1 is returned and the substring isn’t found. Many developers will create a constant value to help, which makes the code more readable, by the way.

 

checkCustomerName: function (customerName) {

 

       const NOT_FOUND = -1;

 

if (this.orderDescription.indexOf(customerName) !== NOT_FOUND) {

       this.processOrder(this.orderNumber);

}

else {

       this.rejectOrder(this.orderNumber);

}

}

 

An enormous number of existing APIs use precisely this mechanism to report errors. Why might this approach be risky? Well, if the implementation ever changes, or a different API is used, then that error code may no longer work. This kind of error can be difficult to find because the application will continue on, but not function properly. Especially when using existing (third-party) libraries, a clean code approach could be used to wrap the API to throw an error.

 

checkCustomerName: function (customerName) {

try findCustomerNumber(customerName) {

       this.processOrder(this.orderNumber);

}

catch {

       this.rejectOrder(this.orderNumber);

}

}

 

findCustomerName: function (customerName) {

if (this.orderDescription.indexOf(customerName) !== -1) {

       return;

} else {

throw(“not found”);

}

}

 

Now it might seem that the only change here is to add code, but this code is less brittle and allows for easier changes to the approach. It is easier to read and divides code into “normal” processing and “error” processing. Additionally, wrapping may provide a way to consolidate multiple errors into a common error type. Simplifying the exception handling removes extraneous detail and, again, makes, the code cleaner.

 

2 Provide Context

After agreeing that exceptions themselves make the code easier to read and understand, it stands to reason that the exception should provide enough context to determine the source and location of an error. Informative error messages—including the operation that failed, and the type of failure—can also eliminate confusion, resulting in clean(er) code. Extending our example above, if there is no customer name, we should throw a UI error instead of “trapping” a more generic error.

 

checkCustomerName: function (customerName) {

try findCustomerNumber(customerName) {

       this.processOrder(this.orderNumber);

}

catch (SyntaxError(error)){

       throw (new UIError(“Customer Name Required”));

}

catch (Error(error)) {

       this.rejectOrder(this.orderNumber);

}

 

findCustomerName: function (customerName) {

if (this.orderDescription.indexOf(customerName) !== -1) {

       return;

} else if (1customerName === “”) {

throw(new SyntaxError(“No Customer Name”));

} else {

throw(new Error(“not found”));

}

}

 

3 Leave the Program in a Consistent State

We should report our errors when they’re caught; they shouldn’t be caught and then ignored. Errors are thrown, we have to assume, for a reason. Finally, the catch has to leave your program in a consistent state, no matter what happens in the try.

 

Conclusion

To summarize, use exceptions, and catch them using the try-catch construct. A second good practice for SAPUI5 error handling is to be specific in throwing and catching exceptions, as this makes the intent clearer. Finally, exceptions, when thrown, should be caught and addressed.

 

If this is your first look at clean SAPUI5, I recommend checking out the first installment of this series, where we established the need for clean code, alongside other code quality mechanisms like test-driven development (TDD) and static code checking. Part two may also be helpful as it explores clean code conventions including using meaningful (and pronounceable) names and creating small functions.

 

With the information you’ve learned throughout these first three posts, you’re ready to explore the impact of testing on clean code. In a future post, I’ll tie together this blog post and testing, by showing the advantage of starting with a try-catch structure and using that as the basis of TDD testing.

 

Learn more about clean SAPUI5 in this book.

Recommendation

Testing SAPUI5 Applications
Testing SAPUI5 Applications

Take a deep dive into application testing for SAPUI5! Learn how to use QUnit for unit testing and build one-page acceptance tests (OPA) for your components. Isolate and remove dependencies from your code using backend mocking. Round off your education with a start-to-finish example that will show you the ropes!

Learn More
Ian McCallum
by Ian McCallum

Ian McCallum is an executive advisor for project success at SAP America. He has worked as a solution engineer and architect at SAP and led several SAP projects in participation with SAP partners.

Comments