-
Notifications
You must be signed in to change notification settings - Fork 518
Description
Is your feature request related to a problem? Please describe.
Error handling takes up a lot of space in the code and makes it hard to read.
Describe the solution you'd like
As a new programmer in OpenFAST, I find it difficult at times to follow the code. The first thing I usually do when I enter a piece of code of OpenFAST I've never seen, is that I delete most of the empty lines and the error handling lines. As a rule of thumb, I like when a function does not take more space than a screen in height.
I'm presenting here the approach I'm following for the module ExtPtfm on which I'm currently working. I'd like to trigger a discussion on this issue and see if we can agree on something. I don't suggest changing the existing code, but instead find an approach for new code (or just a green light for the ExtPtfm code I'm writing).
For a given routine, I delete the following lines:
INTEGER(IntKi) :: ErrStat2
CHARACTER(ErrMsgLen) :: ErrMsg2
CHARACTER(*), PARAMETER :: RoutineName = 'ExtPtfm_Init'Instead of these lines, I add the following at the end of the routine:
contains
logical function Failed()
CALL SetErrMsg(ErrStat, ErrMsg, 'ExtPtfm_Init')
Failed = ErrStat >= AbortErrLev
if(Failed) call cleanup() ! OPTIONAL, if a cleanup routine exists
end function FailedWhere the function SetErrMsg is similar to the NWTCIO library function but it does not use the temporary variables ErrStat2 and ErrMsg2.
subroutine SetErrMsg(ErrStat, ErrMess, RoutineName)
INTEGER(IntKi), INTENT(IN) :: ErrStat ! Error status of the operation
CHARACTER(*), INTENT(INOUT) :: ErrMess ! Error message if ErrStat /= ErrID_None
CHARACTER(*), INTENT(IN ) :: RoutineName ! Name of the routine error occurred in
if (ErrStat /= ErrID_None) then
ErrMess = TRIM(RoutineName)//':'//TRIM(ErrMess)
end if
end subroutine SetErrStatSimpleThen in the routine, I replace
CALL AllocAry(u%BlPitchCom, p%NumBl, 'BlPitchCom', ErrStat2, ErrMsg2)
CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
IF (ErrStat >= AbortErrLev) THEN
CALL Cleanup()
RETURN
END IFby
call AllocAry(u%BlPitchCom, p%NumBl, 'BlPitchCom', ErrStat, ErrMsg); if(Failed()) returnThe function SetErrStat can still be used to set an error message manually.
The solution I'm suggesting only adds the routine SetErrMsg to NWTC_Library and it keeps the error handling philosophy already in place. Yet, it can save thousands of lines and I believe it increases the readability, especially for newcomers. I'm not sure Failed and SetErrMsg are the best names.
Obviously I'm opened to other solutions that would also go in the direction of readability and concise error handling. I just wanted to start the discussion.
Additional option
An additional option, is to use goto. It's a dangerous and controversial construct, but I would argue that it's actually well suited if it's sole use is for error handling at the end of a method. Unfortunately (or fortunately), it's considered obsolete as of Fortran 95.