Case / Real-World Examples
Case / Real-World Examples
Real-World Examples
In this section, we showcase real-world examples of error handling in D projects. These examples demonstrate how error-handling utilities like error(), warning(), and SARIF support are used in practical scenarios.
Example 1: Error Reporting in a CLI Tool
Context:
A CLI tool for file processing needs to validate user input and handle errors gracefully.
Code:
import std.stdio;
import std.file;
void main(string[] args) {
if (args.length < 2) {
error("Usage: filetool <filename>");
return;
}
string filename = args[1];
if (!exists(filename)) {
error("File not found: %s", filename);
return;
}
writeln("Processing file: ", filename);
}
Key Points:
- Error Reporting: Uses
error()to display clear, actionable error messages. - Validation: Checks for missing arguments and file existence.
Example 2: SARIF Integration in CI/CD Pipeline
Context:
A CI/CD pipeline uses SARIF output from the DMD compiler to track and analyze errors across multiple builds.
Workflow:
- Compile the project with the
-verror-style=sarifflag. - Redirect the SARIF output to a JSON file.
- Use a SARIF viewer (e.g., in Visual Studio Code or GitHub Actions) to visualize errors.
Command:
dmd -verror-style=sarif -o- source.d > errors.sarif
Example SARIF Output:
{
"version": "2.1.0",
"$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0.json",
"runs": [
{
"tool": {
"driver": {
"name": "Digital Mars D",
"version": "2.101.0",
"informationUri": "https://dlang.org/dmd.html"
}
},
"results": [
{
"ruleId": "DMD-error",
"message": {
"text": "Undefined identifier `x`"
},
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": "source.d"
},
"region": {
"startLine": 12,
"startColumn": 5
}
}
}
]
}
]
}
]
}
Key Points:
- Standardization: SARIF provides a consistent format for error reporting.
- Automation: Enables integration with tools to automatically analyze and triage errors.
Example 3: Custom Diagnostic Handler
Context:
A developer wants to redirect all compiler warnings and errors to a log file.
Code:
import std.stdio;
import dmd.errors;
DiagnosticHandler customHandler = (ref const(Loc) loc, Color headerColor, const(char)* header, const(char)* messageFormat, __va_list_tag* args, const(char)* prefix1, const(char)* prefix2) nothrow {
auto logFile = File("error_log.txt", "a");
logFile.writefln("[%s:%d:%d] %s", loc.filename, loc.line, loc.column, header);
logFile.close();
return true; // Suppress default error output
};
void main() {
diagnosticHandler = customHandler;
error("example.d", 5, 10, "Undefined variable `x`");
}
Key Points:
- Customization: Redirects error messages to a log file.
- Flexibility: Allows developers to suppress or modify default behavior.
Example 4: Handling Deprecated Features in Libraries
Context:
A library author wants to deprecate a function but provide a clear migration path for users.
Code:
void oldFunction() deprecated("Use `newFunction` instead.") {
writeln("This is the old function.");
}
void newFunction() {
writeln("This is the new function.");
}
void main() {
oldFunction(); // Generates a deprecation warning
newFunction();
}
Key Points:
- Deprecation Warning: Informs users about deprecated features.
- Migration Guidance: Provides clear instructions for moving to the new API.
Example 5: Error Handling in a Web Server
Context:
A D-based web server needs to handle runtime errors and ensure graceful recovery.
Code:
import std.stdio;
import vibe.d;
void handleRequest(HTTPServerRequest req, HTTPServerResponse res) {
try {
// Simulate error
if (req.path == "/error") {
throw new Exception("Simulated error");
}
res.writeBody("Hello, World!");
} catch (Exception e) {
res.statusCode = 500;
res.writeBody("Internal Server Error: " ~ e.msg);
error("Error handling request: %s", e.msg);
}
}
void main() {
auto settings = new HTTPServerSettings;
settings.port = 8080;
listenHTTP(settings, &handleRequest);
}
Key Points:
- Runtime Error Handling: Uses
try/catchto handle unexpected issues. - Graceful Recovery: Ensures the server remains operational despite errors.
Lessons from Real-World Examples
- Use Clear Messages:
- Always provide actionable and user-friendly error messages.
- Leverage SARIF:
- Integrate SARIF for structured and automated error analysis.
- Customize When Needed:
- Use
DiagnosticHandlerfor tailored error processing.
- Use
- Plan for Deprecations:
- Inform users about deprecated features and offer migration paths.
- Ensure Graceful Recovery:
- Always handle runtime errors to maintain system stability.
Key Takeaways
- Real-world applications of D’s error-handling utilities include CLI tools, web servers, and CI pipelines.
- SARIF integration and custom diagnostic handlers provide flexibility for advanced use cases.
- Following best practices ensures error handling is robust, user-friendly, and maintainable.