Is protobuf a good choice of the universal data model? [closed] - c#

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 11 months ago.
Improve this question
We are trying to find a universal data model, which can be applied everywhere.
I think there is no doubt that protobuf is good in the microservice architecture as a protocol among processes of different platforms (Windows, Linux, etc.) and languages (Java, C#, C++, Python, etc.)
But how about using protobuf within the process?
To make it simple and easy to illustrate the problems, let say I am making a C# gRPC service and GUI (gRPC client).
After some study, it seems that it is not suitable from what I can see.
Stability: It looks like that protobuf is still in a changing phase. For example, removing Optional keyword in proto3, but adding it back again in proto release 3.15.
Data type: The data types in proto are not fully compatible with common data types. For example, decimal. We need to define another complex data type (What's the best way to represent System.Decimal in Protocol Buffers?) and doing the conversion.
Conversion: We need conversion before we can utilize it in the related language. You cannot add the self-defined proto decimal directly in c#.
Repeated conversion: Conversion is not one off, but back and forth. Let say we have this proto object passing through 5 functions and need to have some calculations on the decimal field at each function. That means, we will need to convert the decimal field in the proto object to C# decimal in each function, have the calculation to get the result, convert and assign the result back to the decimal field in the proto object, then pass the proto object to the next function.
GUI control binding: We cannot bind the proto field (for those without an matched type in C#). Even we can specify the conversion to do so in the control somehow, (Indeed, I am not sure if we can/it is good to do so) in simple control, like textbox. It may not be easy for complicated control like datagridview because there may be different built-in editors for different native data types. If we use proto data types, that means we need to write customized editors for them. And also, we may need to define other behaviors, like how to sort them.
Using the auto-generated proto class within the process seems not a good idea to me as the reasons listed above. The above case only focus on C# service and client. When it comes to different languages, the cases should be more complicated.
Although .net soap services are slow and wordy (if you look at the wsdl definition), one thing I appreciate very much is that both the service and the client are using the same object with native data types, which can be used directly without any issue. The conversion is done in the communication directly and automatically.
The way I can think of at the moment is that:
Using proto as a communication protocol only
Write a class (use native/built-in data types) for each proto message type and our own conversion logic. Doing so because I cannot find any framework/lib to do so.
After receiving the proto object, convert it directly to an object with native/built-in types before further processing. (the benefit here is that even there is a major change in proto spec, we only need to change the conversion logic only without affecting other layers).
Am I on the right track? What is common/best practice to resolve the problems listed above?
Any help is highly appreciated!!!

Related

Serializing Events into JSON [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I am working on a serialization system using Json, but I need to save events from Buttons (onClick, onHover, etc.) Is there a way about doing this efficiently? (NOTE: The events are all Actions)
Frankly, it is is terrible idea to try to serialize events.
JSON is usually used to serialize data; events are not data - they are implementation details. Most JSON serializers (or more broadly: most serializers) are not interested in delegates / events, because that isn't relevant to data, so: there's a good chance that anything you'd want to do here will need to be manual. Specifically, the problem here is that an event (or rather, the underlying multicast delegate) is effectively zero, one, or multiple pairs of "instance" (optional) and "method" (required).
The method here is a MethodInfo, and there aren't great ways to serialize a MethodInfo as text (although it is at least theoretically possible, although it would be very brittle vs changes to your code.
The instance, however, is an object - and most serializers hate that; in this case, it would combine object (reference) tracking, possibly of objects not otherwise inside the payload, of indeterminate types (so: possibly needing to store type metadata).
Also, deserializing an object model that allows you to point to arbitrary types and methods is a massive security hole, and is a well-known RCE weakness in serializers that (unwisely, IMO) allow this kind of thing (such as BinaryFormatter; for a longer discussion of this topic, see here).
As for what to do instead: whenever an implementation isn't a great fit for a given serializer, the most pragmatic option is to stop fighting the serializer, and work with it instead of against it. For example, it might be that you can create a model that looks kinda like your domain model, but instead of having events/delegates, it might just have a string[] / List<string> that represents the events you need to apply, and your code would worry about how to map between them (mapping methods to strings, and figuring out what the target instance should be, etc). This avoids all of the pain points above, and additionally means that your data is now platform independent, with the payload and the implementation details (your form layout) separate from each-other.

Json serialization and storage strategy [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
Json is often used in web applications. I set a field in the database to text to store json strings. It may not be a good idea to design a database in this way, but my reason is that the composition of the data may be volatile and does not require external connections. Using Json serialization tools such as Newtonsoft can easily de-serialize a json string from a database into a JObject object, but in a static language program, it will definitely require some more concrete objects to express it, and now I'm facing some Optional options:
De-serialize the json string from the database to get JObject, then
use this object directly
continue to resolve JObject, instantiate a more specific object A, and then use the object A
Option 1 is very convenient for storage and initialization of the read, but when used to get the value string, error-prone. Scenario 2 requires an extra layer of conversion for storing and initializing reads, but it is more intuitive and convenient to use. I am very tangled about which scheme to use.
"More intuitive and convenient to use" is the key here. You should always try to write code in a readable and maintainable way, and if creating model objects for your JSON data helps you achieve this goal, and this doesn't impact performance beyond what's acceptable for your project, do it; the extra conversion layer will be worth it.
Unless there is a reason that you cannot, I would have a concrete dto that your JSON can be de-serialised into. This provides you compile time type safety for all usages (at least after the initial instantiating). I would normally go another step and have a business object class that can instantiate itself from that dto, but that obviously depends on your specific requirements.
On top of type safety, you get a whole bunch more benefits when using a concrete object, but I suspect that at this point I'm preaching to the choir.
One reason you may not be able to is where the content itself is dynamic in nature (and by extension your code expects nothing specific about the JSON string other than maybe that it is well formed). Very few problems are like this though.
So the downside is usually the overhead of the time and effort in writing those concrete classes. Once you have them defined, deserialising them is literally 1 line of code. The trick then is to use a tool to reverse engineer the necessary classes from the JSON string. Due to SO policies, I cannot recommend tools, but if you were to use a search engine that rhymes with frugal and search for something like JSON to c#, you are bound to find a quick way to create those dtos.

Why is there no inverse to object.ToString()? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
It seems like a good design decision that the System.Object class, and hence all classes, in .NET provide a ToString() method which, unsurprisingly, returns a string representation of the object. Additionally in C# this method is implemented for native types so that they integrate nicely with the type system.
This often comes in handy when user interaction is required. For example, objects can directly be held in GUI widgets like lists and are "automatically" displayed as text.
What is the rationale in the language design to not provide a similarly general object.FromString(string) method?
Other questions and their answers discuss possible objections, but I find them not convincing.
The parse could fail, while a conversion to string is always possible.
Well, that does not keep Parse() methods from existing, does it? If exception handling is considered an undesirable design, one could still define a TryParse() method whose standard implementation for System.Object simply returns false, but which is overridden for concrete types where it makes sense (e.g. the types where this method exists today anyway).
Alternatively, at a minimum it would be nice to have an IParseable interface which declares a ParseMe() or TryParse() method, along the lines of ICloneable.
Comment by Tim Schmelter's "Roll your own": That works of course. But I cannot write general code for native types or, say, IPAddress if I must parse the values; instead I have to resort to type introspection or write wrappers which implement a self-defined interface, which is either maintenance-unfriendly or tedious and error-prone.
Comment by Damien: An interface can only declare non-static functions for reasons discussed here by Eric Lippert. This is a very valid objection. A static TryParse() method cannot be specified in an interface. A virtual ParseMe(string) method though needs a dummy object, which is a kludge at best and impossible at worst (with RAII). I almost suspect that this is the main reason such an interface doesn't exist. Instead there is the elaborate type conversion framework, one of the alternatives mentioned as solutions to the "static interface" oxymoron.
But even given the objections listed, the absence of a general parsing facility in the type system or language appears to me as an awkward asymmetry, given that a general ToString() method exists and is extremely useful.
Was that ever discussed during language/CLR design?
It seems like a good design decision that the System.object class, and hence all classes, in .NET provide a ToString() method
Maybe to you. It's always seemed like a really bad idea to me.
which, unsurprisingly, returns a string representation of the object.
Does it though? For the vast majority of types, ToString returns the name of the type. How is that a string representation of the object?
No, ToString was a bad design in the first place. It has no clear contract. There's no clear guidance on what its semantics should be, aside from having no side effects and producing a string.
Since ToString has no clear contract, there is practically nothing you can safely use it for except for debugger output. I mean really, think about it: when was the last time you called ToString on object in production code? I never have.
The better design therefore would have been methods static string ToString<T>(T) and static string ToString(object) on the Debug class. Those could have then produced "null" if the object is null, or done some reflection on T to determine if there is a debugger visualizer for that object, and so on.
So now let's consider the merits of your actual proposal, which is a general requirement that all objects be deserializable from string. Note that first, obviously this is not the inverse operation of ToString. The vast majority of implementations of ToString do not produce anything that you could use even in theory to reconstitute the object.
So is your proposal that ToString and FromString be inverses? That then requires that every object not just be "represented" as a string, but that it actually be round trip serializable to string.
Let's think of an example. I have an object representing a database table. Does ToString on that table now serialize the entire contents of the table? Does FromString deserialize it? Suppose the object is actually a wrapper around a connection that fetches the table on demand; what do we serialize and deserialize then? If the connection needs my password, does it put my password into the string?
Suppose I have an object that refers to another object, such that I cannot deserialize the first object without also having the second in hand. Is serialization recursive across objects? What about objects where the graph of references contains loops; how do we deal with those?
Serialization is difficult, and that's why there are entire libraries devoted to it. Making it a requirement that all types be serializable and deserializable is onerous.
Even supposing that we wanted to do so, why string of all things? Strings are a terrible serialization data type. They can't easily hold binary data, they have to be entirely present in memory at once, they can't be more than a billion characters tops, they have no structure to them, and so on. What you really want for serialization is a structured binary storage system.
But even given the objections listed, the absence of a general parsing facility in the type system or language appears to me as an awkward asymmetry, given that a general ToString() method exists and is extremely useful.
Those are two completely different things that have nothing to do with each other. One is a super hard problem best solved by libraries devoted to it, and the other is a trivial little debugging aid with no specification constraining its output.
Was that ever discussed during language/CLR design?
Was ToString ever discussed? Obviously it was; it got implemented. Was a generalized serialization library ever discussed? Obviously it was; it got implemented. I'm not sure what you're getting at here.
Why is there no inverse to object.ToString()?
Because object should hold the bare minimum functionality required by every object. Comparing equality and converting to string (for a lot of reasons) are two of them. Converting isn't. The problem is: how should it convert? Using JSON? Binary? XML? Something else? There isn't one uniform way to convert from a string. Hence, this would unnecessarily bloat the object class.
Alternatively, at a minimum it would be nice to have an IParseable interface
There is: IXmlSerializable for example, or one of the many alternatives.

Is using var in c# really that bad? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
So I'm creating a connection library for a colleague of mine to save him time on his current project. My colleague will use this library in his c# application to connect to a rest api. Within the library I created Handlers for each request(GET / POST / PUT / DEL). When his application talks to my library i will return the response like this:
return client.PostAsync(url, content).Result;
This returns a dynamic object from the rest api.
Today he used my library and couldn't get it to work in combination with his application for some reason. I told him to use a var and that it would work like this:
var x = API.CreateTraject(parameter1,parameter2);
He refused to use var and ended up spending about 40 min figuring out how to get it to work without it. Then he blamed me for returning a dynamic object and that he will never use var because explicit is better so he told me.
Im normaly working as mobile developer (IOS / Android) where i use var all the time.
Now my question is:
Is it really so bad to use var? Should I convert the response in my library so he can explicitly type it in his application? In my opinion I would rather use var and save some time then spend 40 min trying go make it explicit.
Is it really so bad to use var? Should I convert the response in my library so he can explicitly type it in his application? In my opinion I would rather use var and save some time then spend 40 min trying go make it explicit.
var, in C#, is merely a compiler "trick". There is no dynamic typing involved, and the compiled code is exactly the same. When you hover your mouse over the variable, the IDE will tell you the "real" type that gets used.
Whether he uses var or your actual return type shouldn't matter at all in terms of how you create your library.
If your library is returning dynamic unnecessarily, that may be a different issue, and one which the user may have valid complaints. Unlike var (which is merely a compile time trick), dynamic does change the behavior significantly.
Alternatively, if you're returning anonymous types from your library, you may want to consider making an actual class for your values. Anonymous types are really only intended to be used within a local scope, and shouldn't be part of any public API.
There is nothing illegal with using var, it just lets the compiler figure out what data type the object should be.
The only danger is that you, the programmer, don't know what it is until you mouse over. This can lead to problems where you thought it was one thing, but it turned out to be something else.
It is okay to use var, it's not illegal or anything.
But I think if you know the type of variable, declare the variable with the type. This will make your code easier to read.
It's not bad to use implicit typing, it's just a matter of style. I personally use it a lot simply because it makes all my variable declarations take up the same amount of space, regardless of type.
However, using dynamic definitely can be bad, especially when it's used excessively. It means that type safety checks that can be performed compile-time need to be deferred until run time. Occasionally that's useful, but it can have performance impacts. Unless you really need to return a dynamic, I'd strongly recommend returning a specific type from your API method.
For what it's worth, if your coworker is so opposed to implicit typing he could've just used this:
dynamic x = API.CreateTraject(parameter1,parameter2);
var has nothing to do with dynamic. var is about type inference.
Your methods should not return dynamic to begin with. In any case create Generic Methods and let the consumer (your Colleague) decide what type of object the method will return.

C#: How should ToString() be implemented? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
The problems are:
GUI libraries like to use ToString as a default representation for classes. There it needs to be localized.
ToString is used for logging. There it should provide programming related information, is not translated and includes internal states like surrogate keys and enum values.
ToString is used by many string operations which take objects as arguments, for instance String.Format, when writing to streams. Depending on the context you expect something different.
ToString is too limited if there are many different representations of the same object, eg. a long and a short form.
Because of the different usages, there are many different kinds of implementation. So they are too unreliable to be really useful.
How should ToString be implemented to be useful? When should ToString be used, when should it be avoided?
The .NET Framework documentation says:
This method returns a human-readable
string that is culture-sensitive.
There is a similar question, but not the same.
It seems you have great expectations from a tiny little method :) As far as I know it's not a good idea to use a general method in so many different contexts specially when its behavior can differ from class to class.
Here is my suggestions:
1.Do not let GUI libraries use ToString() of your objects.Instead use more meaningful properties (Almost all controls can be customized to show other properties than ToString)
for example use DisplayMember.
2.When getting some information about an object (for logging or other usages) let somebody decide (another object or the object itself)what should be provided and how it should be displayed.(A strategy pattern may come in handy)
Here is a nice article which explains Overriding System.Object.ToString() and Implementing IFormattable
It depends on the indended usage of your class.
Many classes don't have a natural string representation (i.e. a Form object). Then I would implement ToString as an informative method (Form text, size, and so on) useful when debugging.
If the class is meant to give information to the user then I would implement ToString as a default representation of the value. If you have a Vector object for instance, then ToString might return the vector as an X and Y coordinate. Here I would also add alternative methods if there are other ways to describe the class. So for the Vector I might add a method that returns a description as an angle and a lenght.
For debugging purposes you may also want to add the DebuggerDisplay attribute to your class. This tells how to display the class in the debugger, but it doesn't affect the string representation.
You may also want to consider making the value returned by ToString to be parseable so that you can create an object from a string representation. Like you can do with the Int32.Parse method.
Another wrinkle to consider is the tight integration between ToString and Visual Studio's debugger. The Watch window displays the result of ToString as the value of the expression, so if your method performs any lazy-loading, has any side-effects, or takes a long time, then you may see strange behavior or the debugger may appear to hang. Granted, these qualities are not the mark of a well designed ToString method, but they happen (e.g. a naive "fetch the translation from the database" implementation).
Consequently, I consider the default ToString method (without parameters) to be a Visual Studio debugging hook -- with the implication that it should not generally be overloaded for use by the program outside of a debugging context.
While those in the know leverage the debugging attributes (DebuggerTypeProxyAttribute, DebuggerDisplayAttribute, DebuggerBrowsableAttribute) to customize the debugger, many (including myself) generally consider the default output as generated by ToString and displayed in the Watch windows to be good enough.
I understand that this is a rather strict perspective -- writing off ToString as a debugger hook -- but I find that implementing IFormattable seems to be the more reliable and extensible route.
Personally, I don't implement ToString that often. In many cases, it wouldn't make a whole lot of sense, since a type's main role may be to define behavior, not data. In other cases, it simply doesn't matter because no clients ever need it.
In any case, here are some cases where it makes sense (not an exhaustive list):
If the result of ToString could conceivable be parsed back into an instance of the type without data loss.
When the type has a simple (i.e. not complex) value.
When the main purpose of the type is to format data into text.
I don't agree that there is a conflict between the usage scenarios that you list. When display is the main purpose, ToString should provide a user-friendly text, but for logging (or rather, as you describe it, for tracing) I would say that you shouldn't be tracing a UI-specific element in any case, but rather an object whose purpose is to write detailed trace data.
So there is no conflict because it should not be the same type according to the Single Responsibility Principle.
Remember that you can always overload the ToString method if you need more control.

Categories