Then it'd be something like:
RouterMessage.utf8_xml_header
or shorter if you decided on utf8 across the board.I can only imagine the chaos if you start encoding a mixture of Latin-1 and UTF-8 headers :)
1. Static typing can help in reducing the function name.
2. Programming Languages give us means of combinations and abstractions in order to avoid that exact problem.
For example:
class RMG_Serialize inherits Serializor:
router_msg_header rmg
xml_utf8 utf8() {
...
super(this.rmg)
...
}
}The example is not perfect, the function is not exactly globally visible, but I could argue that instanciation of the class is available globally. Or you could get by, by making it static. Also, it's true that I'm adding more characters than any other function name, but no single word I wrote has more than 13 character keeping it easy to read. Every subsequent call to this function will be nothing more than `RMG_Serialize().utf8()`.
Imho, if you feel you're forced to give this kind of name to your variables, there's something wrong either with the design or with the specs.
The choice of programming language counts as well. I mentioned static typing as the obvious example, but isn't a language nothing more than a framework to name your variables?
But I agree with you that maintaining your names short is difficult. I think this has less to do with technical limitations and more to do with project management issues. Generally, I think that a team that understands the value of refactoring (and manage to afford it) will always be better at avoiding this crippling problem.
The other thing is that I prefer symmetry. I would probably write the function to take and return the same thing.
Finally, I might strongly consider writing a generic method that, using reflection, traverses arbitrary data structures and constructs an XML DOM. The caller can do what it needs, e.g. serialize into a string.
If, for some reason, your system requires a specific transformation from a custom data structure into a string, then it belongs in the custom data structure class - possibly a toString method, or something more specific.
RouterMessageHeader.toXMLString();
or XMLSerializer.stringify(routerMessageHeader); RouterMessageHeader.toXMLString();
Ended up as router_message_header_to_xml_string();
So 35 characters in all. Not quite terrible but also not very elegant. At least it says what it does :)I still can't help the feeling that the data structure leaked into the naming of the function and I see no way to solve that, I can't even imagine how one would go about that and still have a function with global scope (in itself something that you'd try to avoid wherever you could, but in this case we can't for various good reasons).
I've looked at making this a generic system but that increases the overall complexity of the bookkeeping (creation, destruction, modification) around the objects to such an extent that it probably isn't worth it (though I can see some other advantages of this approach, such as easier debugging).
send_router_message_header_as_xml_string(...)?
If it also does error handling of some sort, are we going to embed that in the name?My point is still ultimately the same as others here, but I'm trying to demonstrate it from the other direction. It isn't that the long function name is OK, it is that it is poorly decomposed into tasks. But digging another "why" back, the root cause for that is what you say later, that it "increases the overall complexity of the bookkeeping" etc., and the reason for that is that C isn't really that good a language for abstraction. After 40 years of experience with it we've managed to create some best practices that carry it far further than anyone could have imagined at the beginning, but when it gets down to it, when you have a language that doesn't abstract very well, you do eventually end up paying the price in functions like that. It probably is the right answer in C, no sarcasm, but that's not the same thing as saying it's the right answer in a more general sense.
(And to be more concrete, C has poor facilities for composing abstractions together without complication and loss. On a feature-by-feature basis you can make it do pretty much anything you want, Turing Complete etc etc, which makes it hard to see in blog-post-sized examples, but they don't wire together very well.)
RouterMessageHeader foo = new RouterMessageHeader();
foo.toXMLString();
There are other ways for foo to be derived, of course, and in many of them you never need to reference the ReferenceMessageHeader class name. msghead_to_xml()
Are there any 53-character function names in the multi-million line Linux kernel?The linux kernel is actually only about 100 K lines. And its naming conventions are not what I'd call an example of elegance either, to put it very mildly (many of the names are quite cryptic and require extensive study of the code around it to understand what a function does). If low symbol length would be an indicator of code quality then we'd all be using fXXXX where X is a digit of your choice.
The longest symbol in the kernel proper that I can quickly locate is 36 characters:
timer_stats_hrtimer_clear_start_info
It uses roughly the same convention that we use in our projects (a quite common one in large C projects): a module prefix
(if possible the same as the filename) an action and a bit that specifies further details.Even with that simple convention it can add up quickly.
And if you start linking against 3rd party libraries you're going to be looking at name clashes sooner or later, even if you're careful. Whoever at mysql decided to expose 'list_free', 'list_add', 'list_delete' and so on with global scope wasn't having their most lucid day. I wished I was kidding.
This is what I get from sloccount, which doesn't count blank lines or comments, for Ubuntu's old 3.0.0 kernel:
Totals grouped by language (dominant language first):
ansic: 9495321 (96.81%)
asm: 241006 (2.46%)
xml: 41486 (0.42%)
perl: 13987 (0.14%)
sh: 4117 (0.04%)
cpp: 3486 (0.04%)
yacc: 2987 (0.03%)
python: 2770 (0.03%)
lex: 1719 (0.02%)
awk: 708 (0.01%)
pascal: 231 (0.00%)
lisp: 218 (0.00%)
sed: 30 (0.00%)
Broken down by path (top 8): SLOC Directory SLOC-by-Language (Sorted)
5474678 drivers ansic=5469921,yacc=1688,asm=1475,perl=792,lex=779,
sh=23
1848085 arch ansic=1609109,asm=237452,sh=690,awk=470,pascal=231,
perl=58,python=45,sed=30
693955 fs ansic=693955
518275 sound ansic=518092,asm=183
481158 net ansic=481062,awk=96
290060 include ansic=288348,cpp=1670,asm=42
118198 kernel ansic=117893,perl=305
53773 mm ansic=53773
Overall I think your naming convention sounds reasonable; C is also my primary language. Your example was just too easy to shorten to resist ;-).That bit is the kernel. File systems, drivers and so on are best though of as plug-ins to the kernel. Architecture dependent code would probably normally expose only one set of symbols rather than all of the code, probably should have included memory management.
Likely if you include all that code you'll turn up a few more longish names, but the net effect is pretty much the same: really long names are rare when you've laid things out properly but 30 characters and up are certainly no exception.
edit: found a reference: http://www.drdobbs.com/cpp/extending-c-with-prolog/184409294
or
public string Serialize(MessageHeader header)
or if you really want to get fancy Serialize<T>(GenericHeaderObject someObject) which would then be called as Serialize<MessageHeader>(header)