It's funny to see but this is just documentation for a COM API function that runs a macro with any number of arguments (depending on the macro you want to run). That's why it doesn't use a typesafe delegate or something more clear but a lot of ugly "object"s; it has to pull it off with the lowest common denominator for .NET and COM. It's also not part of .NET but a generated COM interop shim to make the Excel interface callable from .NET.
The developer ergonomics make more sense when you look at this from the VB side of things (positional or named arguments with everything optional), it's just the interop that is messy.
Also you can refer to a macro from another assembly that is not referenced by your assembly (you couldn't reference an xla addin from an ExcelDna .net addin for instance).
I first saw this "hardcoded" varargs in Scala e.g. https://www.scala-lang.org/api/2.12.2/scala/Tuple22.html (replace 22 to 1-21). I guess it's platform (JVM) limitation? Newer Java also has something like this, but I can't remember which class.
This kind of function overload is present everywhere in the Java collection framework (and probably other libraries). It is a performance optimization (variadic arguments in Java require creating an array), and variadiac overloads also exist (Map.of needs a list of Map.Entry for type safety) for creating collections of any size.
Do note that the created map is immutable. However, you could pass the created map to the constructor HashMap (or another type) to obtain a mutable copy of the Map created using Map.of
It doesn't have the equivalent of variadic templates, which means you can't have something like std::tuple unless you either codegen it or make it not type-safe.
I did the exact same thing in Java for an internal library in order to provide type-safe Unit, Singleton<T1>, Pair<T1, T2>, etc.
I don't think I have seen classes with many parameters to avoid varargs in Java, however I have certainly seen classes with dozens of Type Parameters, I believe some form of code generation was responsible.
> This form avoids superfluous string concatenation when the logger is disabled for the ERROR level. However, this variant incurs the hidden (and relatively small) cost of creating an Object[] before invoking the method, even if this logger is disabled for ERROR. The variants taking one and two arguments exist solely in order to avoid this hidden cost.
Yes. This used to be one of those things that made a significant difference but probably doesn't matter any more. I say "probably" because I haven't seen any code like this that wasn't spat out from a generator in a long time
Speed and convenience, I'd imagine? IIRC, arrays are marshalled as SAFEARRAYs in COM and those things are quite heavy-weight, you'd really rather call a 31-parameter function and pass it 27 NULLs in places of extraneous parameters.
Excel is out-of-proc so it relies heavily on marshaling. It's either that or custom marshaling. Also it's the same interface as is used internally in the application with VBA scripting.
Well, not sure why that's implemented as is, interop is some old technology and there are quirks or whatever. But .NET provides convenience methods/delegates, like typed Action<>[1] (or Func<>) with 16 arguments, so you don't have to explicitly define delegate yourself:
[1] https://docs.microsoft.com/en-us/dotnet/api/system.action-16...
Today as of C# 4 you can for example have optional arguments. Not sure if this applies to this method which surely predates C#4.
PostgreSQL used to have two different APIs for internal/C language SQL functions, with the older one implemented in more or less this manner, but with distinct types for each argument count. The actual function call was then implemented as giant switch on number of arguments which called function pointer with progressively more Datum-typed arguments.
It got deprecated sometime around 8.0 and today it is not even supported (the giant switch got replaced by error message).
This reminded me of writing a `is_set_cover_possible` PL/Python function for Postgres. I wanted to take an arbitrary number of arrays. Apparently it's not possible so I just had to overload the function and hope that I would never need to check more than n arrays...
Right, but you're calling into a huge dynamically typed external app, and that may have entirely different conventions for reasons that make sense in that app (here excel).
Normally, 30 is crazy. But in excel? Who knows...
Also, too many isn't a problem, they're optional, so in practice you'll be treating this as a varargs; there's not much cost to having a few more args. I haven't used this function, but I suspect I'd rarely call in directly anyhow, instead making sane wrappers for various apis you actually care about which in turn call this internally, making the direct call details even less relevant.
It depends on your domain. Some functions are effectively entire programs which can have huge amounts of configuration required. Many R packages expose a single function that can easily take that number of arguments
I have definitely seen more than 10 arguments. Usually these are the god functions that no one wants to touch and keep adding one too many parameters as it is updated to support new features.
My heuristic is to not be dogmatic like that. A constructor for a triangle class may reasonably want to take 6 arguments (3 x- and 3 y-coordinates). In other cases, even four arguments might be better as a config object if those 4 are all very rarely used.
> I think the general feeling is that there are some code patterns that are safe and easy to do with dynamic typing, but impossible with simple type systems or more complex with more advanced type system.
> An example would be Common Lisp's `map` function [0] (it takes a number of sequences and a function that has as many parameters as there are sequences). It would be hard to come up with a type for this in Java, and it would be a pretty complicated type in Haskell.
Returns the temperature of the motherboard if the computer is currently on fire. Smoldering doesn't count. If the computer isn't on fire, the function returns some other value.
---
Though of course, the Microsoft engineer[ing committee] was entirely serious when they wrote the OP's function signature, while I imagine the Be engineer having a laugh while adding it to the SDK and then getting it into the official docs in print.
...whereas in PHP there’s a setting in php.ini with a Hebrew name that will cause the function to spin-lock, pegging your CPU to 100% until it does catch fire, so that you can be sure it’ll always return a value. And it defaults to true.
This looks like the interop libraries auto generated off the Office OLE Automation interfaces. SafeArrays should have existed back then. I imagine this was used instead for perceived developer friendliness vs forcing developers to box up and create a Safe Array to marshall in (more boilerplate).
Don't think it works in this case. In general why there are so many overloads in C# with parameters like arg0, arg1, arg2 and so on is because of the poor performance of the params solution for value types.
Are you looking at the "applyTo" method? I'm not seeing a variadic overload of "invoke", but I'm also not a Java or JVM person. I'm wondering if I'm overlooking something.
EVen in .net that HAS variadics, there are no stack allocated variadics (yet) so you'll often see 8 overloads with foo(T arg1) foo (T arg1, T arg2) foo(T arg1, T arg2, T arg3) and so on up to foo(params T[] args) because you want to avoid the overhead of actully allocating an array only to pass to one method, if you can. You'd think this kind of thing could be unfolded at compile time instead of requiring manual overloads.
Actually it’s not. This is to call any other macro (function), the first argument is the name of the macro as a string, and the other arguments are the parameters that will be provided to that macro, which can be of any type and have any name. So it kinds of need to be that way.
C# does have optional named parameters (see link below). But it is little help here as this is an old COM library for Excel. The documentation says named parameters are not supported for this method, which is a COM interop limitation but not a limitation of the C# language.
You think a product manager was in any way involved with a function signature. I'm fairly certain this didn't come up in more detail than a requirement: "We need to add a way to call a macro...". And the story as told by the PM would be "...and so the engineers added a way".
I've worked with a bunch of PMs on technical products, APIs, etc. and I've rarely met anyone discussing that level of detail or willing or able to make such a decision.
The engineers chose a way that worked and it's likely the best way supported at the time, given the other comments I've read here on HN.
Joel Spolsky was the program manager (true, not product manager) when VBA was added to Excel. He talks about it on his blog.
"As a program manager at Microsoft, I designed the Visual Basic (VBA) strategy for Excel and completely speced out, to the smallest detail, how VBA should be implemented in Excel."
I see your function with many parameters and I raise you this constant: CNLabelContactRelationYoungerCousinMothersSiblingsDaughterOrFathersSistersDaughter
People really do use these relation names instead of given name. Everyone in the family using different names, which is confusing to watch as an outsider as you can't learn their given names. It would be like watching everyone else in a family refer to a single person as "sister", "cousin", "niece", "aunt" etc. No-one uses their given name so you as an outsider aren't sure what to call them.
For other items that native English speakers may not know - I believe in some Indian languages there are different nouns for your uncle and aunt, depending if they are on your father's or mother's side.
I like the Swedish variant of this. It's basically describing the relationsship in terms of closes family ties, so maternal grandfather is "morfar" ie "mother father". Same principle applies to a bunch of relationships:
farmor - father's mother
farfar - father's father
faster - father's sister (abbreviated from "far syster")
moster - mother's sistem (abbreviated)
farbror - father's brother
I like to extend the basic set of these to older generations, so instead of "my mormor's father" it'd be "mormorfar". Very practical!
Its interesting how different languages have evolved, so Inuit have many words for snow because this highlights area's of concern or importance for them. So the fact these language differentiations exist in Indian and Chinese language, highlights an area of concern or importance for them.
In Iceland, surnames use the fathers firstname and sson for son and dotir for daughter, to highlight the relationship in an otherwise small community. Whether that cultural habit is to reduce the incidence of inbreeding I've yet to find out, but it makes me wonder. History and culture gives away a lot of metadata.
It's not at all clear it makes it easier. My great-great grandfathers children and the children of his brother have different last names. That's before dealing with the hassle of married names vs. maiden names for the women.
Most of my family is in Norway and Sweden, and used pretty much the same method as Iceland, except to throw an extra wrench in, a lot of the time people would either use the name of the farm they were born on in addition or or instead of the name derived from their father. Since that could often include extended family, and different owners over time, there might be a proliferation of people with the same last name as you with no close relationship, while someone with a completely different name might be your first cousin.
My last name only exists because one of my ancestors got tired of the name confusion and renamed his farm (changing one letter) because the local area were full of people with the same last name on farms with prefixes like little/large/upper/lower to separate them all, most of whom are not closely related to us due to purchases (the exact same change has happened two different places in Norway; as a result about 50% of people globally with the same last name as me are relatively closely related to me - the other roughly half we've not found a connection point to, but of course one will exist far enough back).
Historically, I believe this is true for all Norse cultures. The most common surnames in Sweden (like Andersson) are afaik based on the most common given names when surnames were changed to be static in families, which was a gradual process a few hundred years ago.
It wasn't "finished" until much more recently than a few hundred years ago.
My great grandfather Søren Kristian Magnussen was born in 1890, and he got his fathers last name. His father, August Magnussen was born Magnusson in 1842 to a Magnus Andersson near Bullaren in Sweden (ignoring the mothers here only because they had no impact on the last names). August's brother Johan Alfred Magnusson had (at least) three children who were named Johansson / Johansdotter born between 1885-1890. So even that late some children's last names were still derived from their fathers first names.
It makes genealogy both easier and harder - on one hand apart from during and after the transition period you get the fathers first name "for free" (most of the time, except when they complicate things by using the name of a farm instead of a last name), on the other hand it makes searches for the transition period a real mess (as if the poor hand writing of everyone involved in record-keeping isn't bad enough).
> In Iceland, surnames use the fathers firstname and sson for son and dotir for daughter, to highlight the relationship in an otherwise small community.
The same happens in most Slavic ("Vladimir Vladimirovich Putin" is basically "Vladimir son of Vladimir Putin"; a hypothetical sister could have been "Ekaterina Vladimirova Putina", Ekaterina daughter of Vladimir Putin) and some Turkic cultures (Nursultan Abishuly Nazarbayev is the son of Abish Nazarbayev), so the theory that this is related to tight nit communities on a small island seems highly unlikely.
I didnt know how the naming system works in other countries, I only know about Iceland and UK, but I still suspect the naming exists to highlight relationships. The point I'm trying to make is that when the naming system was introduced or adhered to in an area on this planet, I wonder if they knew about the problems of inbreeding, you see here in the UK, with livestock, you typically have a one or two studs and the rest of females, so there is an element of inbreeding or deviation towards it. Pig farmers will have two or three bores fertilizing the sows, cows will get a bull and roosters are also limited to one for a brood.
So did/does some cultural naming system highlight a lack of inbreeding knowledge or not when considering when it was introduced?
“ Whether that cultural habit is to reduce the incidence of inbreeding I've yet to find out, but it makes me wonder.”
That’s racist. “The only way these people are going to be able to stop fucking their cousins as if they come up with a naming system that makes it extremely clear who is related to who.” There are probably other explanations other than being inbred as to why they do this. Like how some people go by Junior or Senior. Do you think that’s to prevent inbreeding also?
Knowing who is related too closely to you can be a problem on a small island, the comment was possibly referencing the Icelandic dating-app that tracks if you share a grandparent with someone you meet in a bar[1]; a feature the app itself calls a "Sifjaspellsspillir", or "Incest Spoiler".
Interestingly the article mentions that this is a problem precicely because of the Icelandic naming scheme:
> Neither patronymic or matronymic, instead each person's father's first name becomes the child's last name. Each new generation has a completely different name to the name of the generation that preceded it. Cousins, aunts, uncles, nieces, nephews -- all could have very different names.
Many other languages do. I think all Chinese languages do, but you don't need to go that far. Even German/Dutch/Frisian/Swiss do have it, although nowadays few use them and many people don't even know. (Father's siblings are Onkel/Tante cognate to uncle/auntie, but Mother's siblings are Oheim/Ohm/Öhi if male and Muhme/Muoike if female.)
> I believe in some Indian languages there are different nouns for your uncle and aunt, depending if they are on your father's or mother's side.
Not only that, but in some cases depending on their (the uncle and your father) relative age. I'm learning Hindi, so for example paternal uncle older than your father is your taaya (ताया, or taauu ताऊ) but younger than your father is your chaacha (चाचा).
This is also the same in Arabic. There are separate words for paternal/maternal aunt/uncle, and by extension your cousins who are "son/daughter of paternal/maternal aunt/uncle".
I've seen this explained before; from memory, it's a type of cousin, with specifiers:
Chinese has distinct words for relatives of the same generation (siblings, cousins) who are older or younger than oneself. Like "big brother" and "little brother" in English, but you always include the big/little part. "Younger" specifies that this cousin is younger than the person whose contacts book this is.
Female - Chinese has separate words for male and female cousins
The rest of the word salad specifies a relationship that is approximated by answering the question "is her (maiden) surname the same as my (maiden) surname?" in the negative — either she is a daugher of one of my mother's siblings, and doesn't share my surname because I have my father's surname, or she is my father's sister's daugher, and thus has her father's surname, which again is not the same as mine.
In English, your male siblings are "brothers", and female siblings are "sisters", regardless of age.
In Chinese, we differentiate between younger and elder siblings. Your elder brother is 哥哥, younger brother is 弟弟; elder sister is 姐姐/姊姊, and younger sister is 妹妹.
I honestly don't know if I would prefer CNLabelContactRelationYoungerCousinMothersSiblingsDaughterOrFathersSistersDaughter or CNLabelContactRelationBiǎoMèi (is unicode even allowed?). And I probably butchered that romanization and upset half the internet in the process.
Then about 80% of the world wouldn't know how to pronounce it.
A quick test in google would suggest that CNLabelContactRelationBiaoMei doesn't introduce too much ambiguity (first result for Biao Mei is still about the correct term), so even without unicode it might be fine.
I've basically just said that, e.g., instead of the identifier EmployeeTheNumberThatIdentifiesATupleInARelation, you should really be using the identifier EmployeePrimaryKey. That is, you usually refer to things using the name of the respective concept, not by describing what the thing's concept is every time you're trying to refer to the thing. It's called "coining a term". Or, in programming, abstraction (as per SICP, that is giving a name to some compound construct so as not to be forced to repeat it endlessly).
Also don’t chinese family relationships distinguish beetween maternal and paternal-side relationships? E.g. a cousin on your father’s side is called / qualified / described differently than a cousin on your mother’s side?
As I understand, only children of father's brothers can be prefixed with 堂, because they have the same last name and are traditionally considered to be in the same house. All others, including children of father's sisters, are all prefixed with 表.
Isn't that "Kleincousin" in German? "Younger" could certainly match the "Klein" part. That would be the daughter of your cousins, so there's surely a male variant too.
I'm German and I never heard the term "Kleincousin". According to Wikipedia [0] it seems to be used regionally to refer to 2nd degree cousins (which I would call "Großcousin").
Anyway, "Kleincousin" and "Großcousin" don't imply the age of the cousin, but a degree of relationship (with regional differences to what is actually meant).
To refer to a younger cousin, I would just say "jüngerer Cousin". "kleiner Cousin" may be possible too (like "kleiner Bruder" for a younger Brother), but it sounds a bit like childs talk and it may not be immediately clear to everyone what is meant.
A more brief, but less objective, way of saying this is "young female cousin via female parent". As others have pointed out, the Chinese care to track this relationship.
> "cousin outside your family" is an oxymoron in most of the western world
It's a tangent, but I would actually argue that in the Western world, all cousins are outside your family and the concept of a cousin belonging to the same family as you is the unthinkable one.
In the Netherlands at least, we use "familie" to refer to the extended family. To talk about the immediate family or one's household, we would use "gezin" (Although I think some parts of the Netherlands may use "familie" for the nuclear family as well? Not where I live, though.)
We don't generally distinguish between matrilineally and patrilineally related family, which is what the "cousin outside the family" was originally about.
Using one word for your family and an unrelated word for your other relatives, including your cousins, doesn't make it sound like your cousins are part of your family. That's a sharper distinction than is drawn in English.
This isn't a question of the pronunciation of the word you use to refer to remote relatives. It's a question of the social relationships that exist between you and your relatives.
Regardless of the domain: classes with And or Or in them are at the very least a codesmell. Because the name even implies it does more than one thing (SRP)
It's not a class, it's a variable. The Or is there because the same Chinese word refers to two possible relationships within a family tree. It doesn't do more than one thing, it represents more than one relationship. If the word 'Sibling' didn't exist, we could use 'BrotherOrSister' in its place.
But I've honestly never encountered this. Not in a valid domain concept. Where "valid" means it is truly embedded in the domain: and not some historical artifact that has been carried along for far too long¹
I'd love to see what valid real-world use-cases there are for an "FooOrBar" or "BarAndFoo" domain concept.
--
¹ Which is a conundrum, I know. If some legacy system or even legacy software was badly designed (or not designed at all, but just evolved over time) carries along its "design flaws", after so many generations or iterations, it becomes the domain concept itself.
You've caveated the "valid" answers out of existence. But here are some examples of or-ed concepts:
* parent or legal guardian (shows up on legal forms all the time)
* state or province (an English language political construct)
* DNS name or IP address
You could argue that "parent of legal guardian" is a legacy concept since it really just means "legal guardian", but it's literally written on legal forms, so it's a domain concept, except if you believe it shouldn't count because it's an anachronism.
You could argue that we don't need "state or province" since we can just say "region", but "region" doesn't mean "state or province" colloquially, and we have to be careful not to refer to Ontario as a state, so the distinction is important. Ironically, that distinction does not exist in Chinese, but it does in English.
"DNS name or IP address" absolutely are two different concepts, it just happens that URL's were specced to accept both as the "host" segment. So whether or not it counts as an example depends on whether you believe that the act of coining the term is also the act of erasing its status as an "or" relation. Alternatively, if you're implementing a web browser, that distinction absolutely does exist because you need to know not to try to resolve an IP address as a DNS name.
I agree about the first two. The legal one being the most strong.
WRT "state or province": I've modelled quite some GIS data and tend to follow abstractions laid by OSM here. Where "state" is very different from "province" because in many locales that is the case;
But maybe your model is purely Chinese and the OSM model -albeit being global- has a poor local fit.
The latter: nah. It's the one I know about most, and I'd say, depending on your use-case, "address", "host", "location", URI, URL, etc are a better name for what you are modeling than "DnsOrIpAddress". If only for the fact that this can be read as "DNS Address Or IP address" as well as "DNS, or IP-Address". It is truly a bad name in many situations.
and, as many people pointed out, the actual domain concept is in Mandarin, and a single word.
So a perfect example of the word "Or" that does not denote a logical disjunction but a translation-artifact. I thought it was obvious that it is not literally implied the letters O and R are never allowed after each-other in code. I mean: obviously having a class named OrGate in an electronics simulation is fine. As is OrParty in a system modeling Israelian politics.
This is about the word Or denoting that your class, value, type, variable, model etc, is One Or The Other.
Then I'm not really sure what your point is. People were talking about the specific domain mentioned, then you said "or" is code smell regardless of domain, then people pointed out why it's _not_ code smell in this domain, then you come back and say "of course it's not code smell in this domain, I was talking about something else".
My point is that if you have a class, or method, or variable that represents "one thing, or another thing" this is a poor abstraction. And that you can "reek" this smell quite clearly if your names contain "one Or the Other" or "One And The Other" the words "Or" or "And".
The example you gave is an artifact of a translation. It is not an indication that this class holds either a "YoungerCousinMothersSiblingsDaughter" class/type/value Or a "FathersSistersDaughter". First, because AFAICS these separate things don't exist. And second because of the first part of that name: `LabelContactRelation`, it being a label; not a return value.
You did pay attention to the part where I explained that this, naturally, is not literally so, did you?
Right, I think you missed my point. If the example being discussed by everyone in this thread does not apply to your point, why did you bring it up in the first place and cause this confusion? And why did you say "Regardless of domain" if that's obviously not true?
All code does more than one thing, and this is not what the SRP (Single Responsibility Principle) is about. The SRP says a module should not implement multiple independent business concerns.
If it is an argument, it is certainly a design issue:
`response_serializer(PersonOrError: person_or_error)` is confusing, impossible to reason about easily, hard to test etc. It signals a way too tightly coupled API, for one. And it breaks the SRP, secondly.
Why not `response_serializer(Person: person, Error: error)` or `try_error(person).then(response_serializer(person))` or many other designs that do the same, but make it explicit where, when and why the distinction is made.
It is something you often see in e.g. Rails, though. And I consider it really poor and confusing API: an example of that dreaded "Rails Black Magick" where a method like `form_for()` can get literally hundreds of combinations of arguments and behaves entirely different according to what is being passed. In runtime. In production. With user-generated content and dynamic typing and all that.
If it is a return-type, there too: why not make it a tuple, or do like Rust: make it an `Option<Some, None>: user` or a `Result<Ok, Err>: user`, the typing now contains this "either/or" not the variable names;
And if it is a class, or even method: it is violating SRP.
Neither of the reasons are absolute. But they all signal that a better solution is possible (but maybe not practical given constraints). Which is fine: but acknowledging this design is lacking (and choosing to still use it) is IMO the correct path; telling yourself that the design is fine, is not.
> And if it is a class, or even method: it is violating SRP.
Not always! Somebody is going to have to discriminate on the argument, and if indeed the caller already knows what they're providing, there's no need to wrap it in an Either -- there should be individual methods for both variants. But if the caller doesn't know what it is yet, and the type represents a domain concept that happens to be a set of options, then there's no reason the caller has to busy itself with that knowledge. To the caller, this might be (actually or morally) an opaque type, and the callee may be where knowledge about it is centralized, and hence where discriminating on the variants ought to happen.
The single-responsibility principle is definitely something that always needs to be kept in mind, but it's not something that can be replaced with broad rules, either.
> If it is a return-type, there too: why not [...] do like Rust: make it an `Option<Some, None>: user` or a `Result<Ok, Err>: user`, the typing now contains this "either/or" not the variable names;
That's exactly what they did -- in the ML-like syntax they used, their `PersonOrError` is exactly `Either<Person, Err>`, but with the type arguments pre-instantiated.
type PersonOrError1 =
| P of Person
| E of Error
type 'l 'r either =
| Left of 'l
| Right of r
type PersonOrError2 = Person Error either
I agree about passing Either types as arguments, I wouldn't do this. Pattern matching solves this problem.
> If it is a return-type
As for making them return types, it forces you to match over them, you can have the compiler do exhaustive matching over the types it can be. If you have a tuple of (int, string), you could store an int and a string. With Either types, it has to be one OR the other, it can never be both.
Like I said, you can pattern match over this depending on what the type contains. It also allows nice binding and failing out the chain early. e.g. something like in a C style syntax:
public Either<Error, int> M()
{
"In M".Print();
return 6;
}
public Either<Error, string> M2(int y)
{
$"In M2 {y}".Print();
return $"{++y}";
}
public Either<Error, string> M3(string y)
{
$"In M3 {y}".Print();
return $"Result {y}";
}
public void ShowResult(string y) => y.Print();
public void DisplayError(Error error) => error.Message.Print();
M().Then(M2)
.Then(M3)
.Match(left: DisplayError,
right: ShowResult);
So, the functions that operate on the Either types only ever take the right type of the Either. If say M2 returned an Error, M3 would never be called and you shortcut to the error handler.
The match forces you to explicitly handle if it's an error or not.
I like this pattern, it can be concise and expressive when used in a context where it's applicable.
> And if it is a class, or even method: it is violating SRP.
I disagree, the Person class is just a Person (and nothing else), the Error class is an Error and nothing else. The Either class is generic and is a way to hold Either of multiple types (but only one at any time).
> make it an `Option<Some, None>:
I like Rusts option type, but the problem is the None state doesn't collect information, but I think it's certainly a nicer alternative to null. Again you can compile time enforce pattern matching to ensure you handle both states.
> Result<Ok, Err>: user`
Assuming Result can only ever be OK or Err, this is basically an Either type!
> Assuming Result can only ever be OK or Err, this is basically an Either type
Yes. It is the same concept.
SRP is rather vague, and interpreted differently depending on when and where to apply it (SRP for microservices is very different from SRP for a method).
But for the Either, or the Result, it applies perfectly. Because this thing does only one thing: it discrimates between this or that: it leaves what this and that do, are, mean etc to this and to that.
I was trying to put forward examples where the code does both this discrimination and applies the resulting meaning from it. In dynamically typed languages a bigger problem than in many others, where e.g. "null" or "some object of type X" or "a string with the error message" are far too common as return values.
Not necessarily. If your code is in English, and your category does not exist in English (like this Chinese word described here), then I do not see how to do better than this salad.
While wordy, the class name is representing a real relationship that users care about. The developer could have borrowed the underlying word from e.g. Mandarin, but then it would be weird to use that when set to Cantonese.
I guess stdarg.h like functionality would have been good for C#. Maybe some clean code purist argued against it because it is bad practice or something.
There is, it's called "params" [0], and it has been there since C# 1.0. But the link is about the Excel's interop, and that thing originally dates back to, I don't know, 1993 or somewhen around that time? It never was dropped/redesigned due to backward compatibility, so the latter improvements were simply bolted on top of it.
Oh didn't know that. And here I am trying to be smug. Seems to only take the same type though? However in this case it would work since they are all Object.
This is exactly why I dropped using C# and wend back to Java. Documentation on Microsoft products is really bad sometimes.
EDIT: Thanks for the downvotes. I am a professional software engineer for hire and in each company this is EXACTLY the issue: documentation. You want me to help you build software? Fine: give me your documentation. Complain about the fact that it takes 2 months to properly understand your software and business rules? Improve your documentation.
I agree that the DCOM interface by IBM (20 years ago?) was just as bad... but if the source does not provide any documentation how can you be more clearer if you open it up in another language?
Around ten years ago I would have agreed, MSDN was fairly nice, pretty comprehensive even if a bit full of seemingly autogenerated descriptions like "FrobnicateBar: Frobnicates the bar and return result" at the edges. Nowadays? Not so much.
With MSDN docs the older the doc the better it is. Pick something from the early days of win32 and it is a 10 page doc, very well done. Pick something they made up last month and you usually get very basic things. It has been that way for a long time. I remember the orig .NET docs were terrible to use. They have improved decently over the years. I can not prove it but I suspect the docs are only improved when a support case necessitates it.
The args have to be object/variants, as it is the values for the sub that will be called and they can have any type. You would use generics today but keep in mind this is 1990s API.