2

In the project I am working right now, we have some python and some C# code. At some point, I call from python a subprocess which starts a C# executable. This C# code returns an error code, which has to be understood on the python side and a readable report has to be created.

This means, both sides "must speak the same language". So, at the end I have to handle a mapping {error codes: readable explanation} (normally we implement this as static properties of a enumeration class). This is of course a case of code duplication, and prone to be inconsistent.

My ideas to mitigate this have been so far:

  • Automatically generate code: let's say when the mapping on the C# part changes, the code will be parsed and automatically generated on the the python side. While I think this is technically quite correct, I have to somehow parse C# code and translate it to valid python code, which is something probably hard to get it right at the first time.

  • Partial processing of error code on the python side. This means, just check for zero or non-zero return value, and if non-zero, read the stdout of the C# process and report it, no matter what. While this is very easy to implement, I see some possible caveats, like the C# process crashing in an unexpected way and reporting some exception traceback or similar.

Since this must be a quite common problem, I would like to know what are the easiest and more maintainable approaches used in the industry.

1

Rather than parsing C# code, my suggestion would be to store the error codes and their associated descriptions in external resource files (XML, JSON, CSV, database table, whatever). That way all the Python code has to do is look up the code and retrieve the human-readable description. This will also allow you to add localization/translation support or update texts without redeploying code.

  • But this still binds an arbitrary number with the meaning of the error code. For instance, the C# code will return the number 33, meaning that "resource could not be found". This (implicit) binding of numbers and explanations is still duplicated on both sides. However, your idea is good with some minor changes. I can use a mapping between error labels and numbers, like {'resource_not_found: 33}, and if the error shows up, the C# process can look up the label and return the code. – bgusach Feb 23 '15 at 12:56
  • I might be missing something, but I understood that the C# process returns the errors, and thus is, by necessity, returning a set number of possible errors, because this process is where the business logic happens. – Avner Shahar-Kashtan Feb 23 '15 at 12:59
  • The c# process returns the codes, of course. The thing is that the conceptual mapping of "33 means resource not found" has to be shared by both parties, which may lead to inconsistence issues. Maybe I am misunderstanding how the APIs should work, and the C# should not care at all about who is calling it (if it was an external 3rd party, this would be the case actually). – bgusach Feb 23 '15 at 13:15
  • Yes, this is what I was going for: the C# process returns error 33, which means resource not found. It doesn't care about readable strings or display - just the logical meaning of the error code. It's the client application ("client" here meaning "app that displays or writes human-readable data") to translate it to something readable. – Avner Shahar-Kashtan Feb 23 '15 at 13:17
  • We are getting tricky here, but it is not about the readability, but the mapping numbers->error reasons, i.g. {33: 'resource_not_found'}. My idea was, that when the c# code hits the error case, instead of just returning 33, it think: ok, I have a 'resource_not_found' (which is arbitrary as well, but more programmer-readable), so let's look up what I have to return... 33? ok, there you go. – bgusach Feb 23 '15 at 13:22
1

I would use code generation from single source.

E.g. define error codes in a text file and use T4 to generate C# enum and something similar to generate python code. Or write C# enums directly and use code generation to generate python only. You dont have to parse C# code necessarily, you can use some .net tool that dynamically loads your .net assembly and uses reflection to get enum members. Why not to use T4 to generate python enums as well? :)

I believe code generation is the best way to avoid violation of DRY principle in this case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.