202 lines
5.3 KiB
Markdown
202 lines
5.3 KiB
Markdown
# NASA-style Programming for C#
|
|
|
|
I asked the coding AI to write their [system prompt](Powerof10PPrompt.txt) in the form of programming guidelines. They're based on NASA's [Power of 10](https://en.wikipedia.org/wiki/The_Power_of_10:_Rules_for_Developing_Safety-Critical_Code). I figured I'd use C# since it's both my preferred language and the language's syntax should be fairly easy to grasp once you understand the basics.
|
|
|
|
My only request was to apply .NET 6's [top-level statements](https://learn.microsoft.com/en-us/dotnet/csharp/tutorials/top-level-statements) for brevity. Aside from a few organizational changes, minor tweaks to section 8, and adding the `Program` class to the scope example, it all works flawlessly.
|
|
|
|
Why NASA? Their coding standards have loads of redundancies, and if AI is going to behave like advanced code generation tools, they need to be as fault-tolerant as possible. While my instructions were modified to account for modern languages, the principles are still the same.
|
|
|
|
## 1. Write Clear, Well-Structured, and Maintainable Code
|
|
|
|
- Keep the code simple and coherent. Use meaningful identifiers and limit the complexity of expressions.
|
|
- Keep functions or methods short, with a single responsibility.
|
|
|
|
### Example:
|
|
|
|
```csharp
|
|
// Good example of a short, focused method
|
|
int Sum(int a, int b)
|
|
{
|
|
return a + b;
|
|
}
|
|
|
|
// Good example of clear, well-structured code
|
|
var result = Sum(5, 3);
|
|
Console.WriteLine($"The sum is {result}");
|
|
```
|
|
|
|
## 2. Follow Best Practices for Security, Performance, and Reliability
|
|
|
|
- Validate and sanitize inputs to prevent security vulnerabilities like injection attacks.
|
|
- Use try-catch blocks to handle exceptions gracefully.
|
|
|
|
### Example:
|
|
|
|
```csharp
|
|
using System.Globalization;
|
|
|
|
string userInput = "2023-10-30";
|
|
if (DateTime.TryParseExact(userInput, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime date))
|
|
{
|
|
Console.WriteLine($"Parsed date: {date}");
|
|
}
|
|
else
|
|
{
|
|
throw new FormatException("Invalid date format.");
|
|
}
|
|
```
|
|
|
|
## 3. Ensure Portability and Adaptability Across Different Environments
|
|
|
|
- Use environment variables or configuration files for environment-specific settings.
|
|
- Rely on cross-platform libraries within .NET.
|
|
|
|
### Example:
|
|
|
|
```csharp
|
|
// Reading configuration using environment variables
|
|
var configValue = Environment.GetEnvironmentVariable("CONFIG_KEY");
|
|
if (configValue != null)
|
|
{
|
|
Console.WriteLine($"Configuration value: {configValue}");
|
|
}
|
|
else
|
|
{
|
|
throw new InvalidOperationException("Configuration key not found.");
|
|
}
|
|
```
|
|
|
|
## 4. Manage Resources Efficiently and Safely
|
|
|
|
- Prefer `using` statements to safely manage resource cleanup.
|
|
- Avoid excessive memory allocation and prefer stack-allocated variables.
|
|
|
|
### Example:
|
|
|
|
```csharp
|
|
// Using statement to ensure safe disposal
|
|
using (var reader = new StreamReader("example.txt"))
|
|
{
|
|
string line;
|
|
while ((line = reader.ReadLine()) != null)
|
|
{
|
|
Console.WriteLine(line);
|
|
}
|
|
}
|
|
```
|
|
|
|
## 5. Use Minimal Scope for Variables and Functions
|
|
|
|
- Limit the visibility of variables and functions to the smallest scope necessary.
|
|
|
|
### Example:
|
|
|
|
```csharp
|
|
namespace Application;
|
|
|
|
class Program
|
|
{
|
|
static void Main()
|
|
{
|
|
// 'a' and 'b' are limited to Main method scope
|
|
int a = 5, b = 3;
|
|
Console.WriteLine($"Sum: {Add(a, b)}");
|
|
}
|
|
|
|
static int Add(int a, int b)
|
|
{
|
|
// 'a' and 'b' are limited to Add method scope
|
|
return a + b;
|
|
}
|
|
}
|
|
```
|
|
|
|
## 6. Always Validate and Sanitize Input
|
|
|
|
- Sanitize and validate all external inputs to secure your application.
|
|
|
|
### Example:
|
|
|
|
```csharp
|
|
using System.Web;
|
|
|
|
string input = Console.ReadLine();
|
|
if (string.IsNullOrWhiteSpace(input))
|
|
{
|
|
throw new ArgumentException("Input cannot be null or whitespace.");
|
|
}
|
|
else
|
|
{
|
|
string sanitizedInput = HttpUtility.HtmlEncode(input);
|
|
Console.WriteLine($"Processed input: {sanitizedInput}");
|
|
}
|
|
```
|
|
|
|
## 7. Documentation Comments
|
|
|
|
- Use XML documentation comments for functions or methods to improve maintainability and provide documentation.
|
|
|
|
### Example:
|
|
|
|
```csharp
|
|
/// <summary>
|
|
/// Sums two integers.
|
|
/// </summary>
|
|
/// <param name="a">The first integer.</param>
|
|
/// <param name="b">The second integer.</param>
|
|
/// <returns>The sum of the two integers.</returns>
|
|
int Sum(int a, int b)
|
|
{
|
|
return a + b;
|
|
}
|
|
```
|
|
|
|
### 8. Use Preprocessors, Macros, or Metaprogramming Techniques Sparingly to Maintain Code Clarity
|
|
|
|
- Preprocessor directives can be useful for conditional compilation but should be used judiciously to avoid obscuring the code.
|
|
|
|
### Example:
|
|
|
|
```csharp
|
|
#if DEBUG
|
|
Console.WriteLine("Running in Debug mode.");
|
|
#else
|
|
Console.WriteLine("Running in Release mode.");
|
|
#endif
|
|
|
|
int result = Sum(5, 3);
|
|
Console.WriteLine($"The sum is {result}");
|
|
|
|
int Sum(int a, int b) => a + b;
|
|
```
|
|
|
|
## Example Using Top-Level Statements in .NET 6
|
|
|
|
Combining several of the above principles:
|
|
|
|
```csharp
|
|
using System;
|
|
using System.Globalization;
|
|
|
|
string userInput = "45";
|
|
if (!int.TryParse(userInput, out int number))
|
|
{
|
|
throw new FormatException("Invalid integer format.");
|
|
}
|
|
|
|
Console.WriteLine($"Parsed number: {number}");
|
|
|
|
void ProcessDate(string dateString)
|
|
{
|
|
if (DateTime.TryParseExact(dateString, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime date))
|
|
{
|
|
Console.WriteLine($"Parsed date: {date}");
|
|
}
|
|
else
|
|
{
|
|
throw new FormatException("Invalid date format.");
|
|
}
|
|
}
|
|
|
|
ProcessDate("2023-10-31");
|
|
```
|