4 ms·
It sounds like you think about error handling a lot. Is there a language that has error handling "done well " that you like?
by appleflaxen 3y ago
It sounds like you think about error handling a lot.
Is there a language that has error handling "done well " that you like?
- janosdebugs 3y agoError handling is a difficult topic. Generally, the more you can catch in the compiler, the less you have to write runtime checks and the obligatory unit tests that everyone likes to forget. So if you are on the lookout for a language, I'd look for something that has explicit nullable/non-nullable types, as well as strict and static typing. However, I wouldn't pick a language purely based on its error handling capabilities. That's treating everything like a nail just because you have a hammer. I'd pick a language that's suitable for the task at hand. Go is suitable for making small(ish) webservices. Over 10k lines of code it becomes really hard to keep things straight. However, that's more due to its very limited scoping abilities. As far as Go is concerned, you can make the error handling work. In ContainerSSH, we built our own logging overlay, which you can find here: https://github.com/ContainerSSH/libcontainerssh/tree/main/log https://github.com/ContainerSSH/libcontainerssh/tree/main/lo... This companion message library has a custom error structure that carries along an error code, which uniquely allows identifying the cause of the error: https://github.com/ContainerSSH/libcontainerssh/blob/main/message/message.go https://github.com/ContainerSSH/libcontainerssh/blob/main/me... Errors can be wrapped and we added tools to determine, if a certain error has an ancestor with a specific code, allowing for tailored error handling cases. We also added a tool that gathers the comments from the error code constants and adds them to the documentation: https://github.com/ContainerSSH/libcontainerssh/blob/main/cmd/generate-message-codes/main.go https://github.com/ContainerSSH/libcontainerssh/blob/main/cm... I hope this helps.
- maleldil 3y ago> Over 10k lines of code it becomes really hard to keep things straight. However, that's more due to its very limited scoping abilities. Could you please elaborate more on this?
- janosdebugs 3y agoWith the default toolchain, Go has essentially two levels of visibility scoping: package-private (lower case) vs. exported (upper case) items, and module-internal vs. public packages (packages in the "internal" folder are not accessible from other modules). To make matters worse, all files in the same folder belong to the same package. (There are other toolchains out there that do things differently.) In larger projects, especially with lots of contributors, I found that you'll want to practice some level of defensive programming because code review can only catch so many errors. In other words, you'll want to make sure that parts of your program only talk to each other via "sanctioned" APIs. Go makes this difficult because anything in the same folder can access data in structures defined in the same folder. For example, the Kubernets backend for ContainerSSH (https://github.com/ContainerSSH/libcontainerssh/tree/main/internal/kubernetes https://github.com/ContainerSSH/libcontainerssh/tree/main/in...) has two parts, one dealing with the integration with the rest of ContainerSSH, while the other deals with Kubernetes. In order to provide some level of separation, we added an interface in the middle to document the package-internal API somewhat: https://github.com/ContainerSSH/libcontainerssh/blob/main/internal/kubernetes/kubernetesClient.go https://github.com/ContainerSSH/libcontainerssh/blob/main/in... However, this is suboptimal and leads to unnecessary boilerplate code. You could, of course, forego the interface, but that would mean that code reviewers would have to make sure nobody is taking the easy route and messing with the internal state of a struct that they have no business messing with. In other words, you'd want some level of encapsulation which is not easily doable in Go. In other languages you have much more granular visibility options, either in an OOP way (private, protected, public, package-private, friend classes, etc), or by providing things like header files that describe an interface between parts of the application.
- maleldil 3y agoThank you for the in-depth response! Just to clarify my understanding, do you mean you want to encapsulate data structures within the same package (i.e. files in the same directory)? If so, I'm not clear why you can't break those up into a different package.
- 3y ago
- deleted 3y ago[deleted]