-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
C# structure isn't DRY #2974
Comments
Razor has a big benefit from the fact that C# doesn't care about whitespace. |
How is whitespace scoping more DRY? You are repeating yourself on every single line by re-affirming what scope you want to be in! And what happens when you copy and paste a bit of code in a language where whitespace has semantic meaning? You can silently give that code different meaning than what you think it has. Whitespace scoping is the part I dislike the most about both F# and Python and am strongly against bringing it to C#. |
It's especially fun when working on a project where people are mixing spaces and tabs. No, white space scoping has no place in C# or any C-derived language, and we're better off for it. There is no lack of CLR languages, including those with white space scoping. I suggest using them. |
This is where Roslyn's static analysis could come in handy. It probably wouldn't be too hard to write an analyzer that errors at what you consider to be bad whitespacing, but please don't make this a language-level feature, because other people will have different opinions on whitespacing (like tabs vs. spaces, as @HaloFour mentioned). |
I'm very much of the mindset that "white space is not code". Style is, and should be in my opinion, a distinctly separate thing from code / logic. I see useful constructs all the time like the following
These are completely legitimate styles and project use what suites them. Enforcing a style isn't going to help the language, but it will break a lot of existing code. |
@breyed You appear to be proposing something but you stop short of telling us what your proposal is. Can you please give an example of the syntax you propose would be supported (in addition to what is already supported, presumably). |
I disagree with the premise. If C# mandated that indentation match the braces, then you would certainly violate DRY. This is not the case. Only the braces determine scope, and only one set of braces is required for each scope. |
Since C# ignores whitespace when determining structure, it is DRY in its normative definition, as @sharwell points out. However, if you write code without repeating yourself you will have unindented and unmaintainable code. So we repeat the C# structure with whitespace, in a variety of styles, as @whoisj shared. Eliminating the redundancy and stylistic differences would both be a productivity boost to development teams. I don't have a specific syntax to solve the DRYness problem in mind (@gafter). Some principles are clear, however. Since indentation is important to programmers, it's is a natural choice to specify scope (not reaffirm scope @MgSam suggested, which implies a succeeding line by default keeps the same scope as its previous line). There needs to be clear rules about the type of whitespace, per @HaloFour's point on tabs vs. spaces. F# deals with this by mandating spaces only, though perhaps a more creative solution allowing tabs along with good editor support to stick with a common style would be even better. Indent-based structure introduces an ambiguity when pasting (per @MgSam). In the C# sequential structure, subsequent text is at the same scope as the previous text, and editors auto-format to put it there. It is explicit because block ends are explicit. With indent-based structure, it is ambiguous as to whether a new line is a continuation of the previous block or a new block. Here's an example:
Despite the ambiguity, there are good choices for an editor to provide the developer a good experience. One choice would be to ask where "bar()" should be placed. Better, however, would be to place the pasted block at the same indent level as the previous line and let the developer move it if desired. Either way, a lightweight syntax would not pose a problem for pasting code from unrelated sources. Moreover, it would be a straightforward editor feature to take pasted code in verbose syntax (e.g. from StackOverflow) and transform it automatically to lightweight syntax, since the language remains otherwise the same. This is an advantage of adding a lightweight syntax to C#, versus @HaloFour's suggestion of using an alternative language. |
I don't do that. I type the syntax specified by the language, and the editor places it in a logical layout that matches what I typed. Indentation-based layout still requires the programming to type characters when changing scope, but relocates these scope-identifying characters from If you are typing more characters in a curly-brace language just to maintain visual clarity, perhaps it means you need to either improve (or request improvements to) the editor's handling of format-while-you-type, or get a better editor. But making it more difficult to manage (in terms of number of characters typed and/or distance your fingers need to travel to type it) is obviously not a desirable answer when measured on the principles you seem to be advocating for. |
Note that braces do not indicate scope. They indicate blocks. The scoping applies to a single statement, and a block qualifies as a statement. As whitespace is entirely optional as is indentation. Yes, there are various common styles used to indicate scope, but there are also many instances where one may want to deviate from a style where it makes the syntax visually clearer. If whitespace dictated scope or blocks that would no longer be an option. You'd be left to follow the rigid whitespace rules despite what would actually look appropriate. No, this doens't belong in C#. It doesn't belong anywhere near C#. It to you braces make for a "heavy" language I don't want to know what you consider to be a light language. I've programmed COBOL (there goes the history claim), CoffeeScript and Python and it is obnoxious to me to be so constrained as to how you're permitted to lay out your code because someone decided to bake their coding conventions into the syntax. |
@HaloFour I'm using the term in a more abstract sense to refer to lexical scope. Even in C#, however, the term "blocks" can be confusing because that's not a standard way to refer to the braces of a |
@HaloFour I've written a fair amount of Python and F# and have yet to encounter a case where I've wanted to indent in a way contrary to the language's rules. Can you provide an example where indent-defined structure would be overly constraining? |
It's a good thing my socks are DRY then, ... oh wait. |
@breyed in my examples, there's nothing "unproductive" about any of them. Simple tools like Astyle and complex IDEs like Visual Studio can be set to automatically format your code. Give the ease by which each developer can format code (so long as whitespace is a non-issue), I completely do not understand your logic. If whitespace were difficult to manage or a requirement for doing work, I'd agree about your DRY concern. At no point do I feel that I am repeating myself when I code C# in Visual Studio. The IDE closes braces, formats indention and whitespace for me, and generally checks that code is compliant. I focus on the logic and flow while retaining a layout (whitespace, indention, etc) that is pleasing to me, requires minimal brain power to parse, and makes me more productive. YMMV |
LINQ method chaining?
If I wasn't allowed to line up the dots because "it's contrary to the language's indentation rules", then it wouldn't be visually pleasing in the slightest. |
@Joe4evr An intent-defined structure can support multi-line fluent APIs. A lightweight C# can use more than just indents to indicate expression continuation (a "." in this case). F# does this. For example, the following is valid F# lightweight syntax:
|
You keep using this word [lightweight]. I don't think it means what you think it means. What does the following mean in CoffeeScript? x.foo 1
.bar 2 Answer: completely depends on the version of the transpiler. And for fun, in order to override the stupidity of the whitespace-sensitivity you had to know two different syntaxes and know when to apply which in order to override the behavior. Do not want. If I wanted F# or Python I'd use F# or Python. The immeasurable effort necessary to bring a completely different form of parsing to C# would provide absolutely no real benefit and would likely provide only much more confusion. All just to avoid curly braces? |
C# is becoming more DRY in general. The proposals in C# 6.0 and 7.0 for import of static type members into namespace, auto property initializers, default values for getter-only properties, and declaration expressions, all remove redundancy without adding any new functionality. Depending on your choice of editor and plug-ins, your tooling will generate much of this redundant code for you (as is the case with indenting, as @sharwell noted). So why all these new features? Because code generation is good, but code elimination is better. For example, ever get confused by code accidentally checked in with incorrect indentation? As @whoisj alluded to, inconsistencies should be rare, since the code can be formatted automatically, but they still happen. We normalize our database schemas to avoid the pitfalls of data inconsistencies. Those benefits apply to code, too. As with the other proposals to lean out C#, removing unnecessary code lets you focus on your logic and gets more of your logic on the screen. A closing brace generally ties up a whole line just to offer a single piece of information that your indentation, if sane, has already told you. C# has a history of learning from the strengths and pitfalls of the languages that go before it. It is inconceivable that the flaws @HaloFour exposed in CoffeeScript would make their way into a lightweight C# syntax. Simply borrowing F#'s approach to specifying which syntax would be sufficient to avoid pitfalls. (BTW, I am borrowing the term lightweight from F# as a technical term, not for purposes of persuasion (the latter would also be inconceivable :)). |
I personally prefer C# syntax over F# syntax, deriving from OCAML was a mistake. More concise != more readable. Besides, there is already a lot of arguing about the best way to format code in current C#. Adding an extra option will make it only worse. PS: @breyed - I noticed you are using punctuation in your English, those commas and round brackets are non-DRY too, but they do improve readability :-). |
Please forgive, @dsaf, in advance, but I just can't resist: punctuation in English is more normative than I think you realize. For example, the commas around your username in this comment indicate its use as an appositive (rather than a direct object as it would be without surrounding commas). The punctuation changes the meaning entirely. Your postscript is a comma splice (a type of run-on sentence). Your comma (which should be semicolon) after English makes commas and brackets modifiers of either punctuation or English. The clause "are non-DRY too" then introduces a parsing error, not due to repetition, but by violating a constraint on verb usage. Fortunately, humans come with excellent algorithms for automatically correcting invalid syntax (reminds me of web browsers). :-) |
@breyed Speaking of syntaxes that have evolved over time. If you rigorously apply what is taught in academia today to English texts written a century ago it wouldn't make much sense. You've still yet to propose an alternate syntax. You have one short example, but all you've done is replace a And none of those other syntax changes drastically alter the basic forms through which C# is parsed. Anonymous delegates in C# 2.0 were probably the last time the basic structure had been altered, but even that kept to block scoping rules. C# does enjoy learning from the mistakes of others, and whitespace scoping is one big mistake you're not going to see adopted. |
Good syntax is often a detailed and subtle endeavor, which is why I focused on just noting the issue. Prompted by @HaloFour's comment, I've given this some thought and would offer the following lightweight syntax. I'd have to dig through the C# spec to get the precise grammatical terminology, but this should give you the gist.
Examples:
BTW, I read Treasure Island to my kids not too long ago. I didn't notice any differences in the English syntax of 132 years ago from that of today. |
@breyed That's about what I expected. You don't want C#. You want another language. Those languages already exist so I imagine that your problem is the inability to find jobs for those languages. The semi-colon elimination proposal was already brought up. Again, C# was not designed for this, and the sheer volume of breaking changes and ambiguities (and the massive effort that would be involved to even attempt to resolve that) make it a non-starter, primarily because there is zero benefit to it. That bears repeating, this proposal provides ZERO benefit. Barring that, your very first example already violates existing C# syntax. The rest of them just make it unreadable. And none of this is even remotely lightweight. I can't comment on Treasure Island. I haven't read it in a long time. You should try the US Constitution, though. Entire court cases have revolved around the interpretation of different passages as written vs. modern English, commas in particular. Not to mention that the English alphabet had more letters then. |
@HaloFour Recall that I suggest having two syntaxes, the existing syntax ("verbose") and a new syntax ("lightweight"). This would ensure no breaking changes. F# was successful with this approach. Ambiguity is another matter. Can you think of an example in which the proposed lightweight syntax would be ambiguous? And speaking examples, I'd love to see an example of a comma-based constitutional court case in which the date of the writing makes any difference, or an example of an additional English letter in the eighteenth century - although over here would be a better place. |
@breyed I continue to contend that you suggest having two languages. Try Googling "supreme court guns comma", the resulting articles/blogs/thesis/etc. are an interesting read. Makes you wonder what Congreſ* was thinking. * How "Congress" was spelled in 1789, as appears in the Bill of Rights. |
Braces in Razor are a pain if you're trying to keep the newlines tidy in your output HTML. For example, the following leaves an extra blank line before the table close tag.
What if we could drop the braces?
@GeirGrusom, do you have an example in mind of the benefit to Razor of C# not caring about whitespace? |
Razor can just convert everything between I would also like to mention that mixing tabs and spaces, or getting the number of spaces wrong, either by copy-paste or poor merge conflict resolution, can introduce bugs in the code if C# cares about white space. And the benefit is non-existent in my opinion. Python, OCaml and F# all care about white space, and I would say in F# it's an annoyance, and it's one of the least noticeable features of Python. So why bother implementing it in C#? Also imagine if C cared about white space. We would never have had The International Obfuscated C Code Contest! |
@gafter Yes and no. The specific functionality of Visual Studio required to support my argument is implemented in Roslyn components which are not strictly tied to Visual Studio. While I don't know of another editor implementing them in precisely the same way, the barrier to do so is not nearly as high as it once was. |
I would say, as I understand it: C# is developed and compiled with Roysln, which comes with facilities to format code. Therefore any argument about various IDE is moot and off point. Since the compiler service itself supports code formatting, the existence of code formatting utilities is always available. Therefore code formatting should not be considered part of the equation for evaluating if C# is DRY enough. Personally, I prefer my language a little moist 😏 . |
I agree, enough code editors with even basic support for C# have brace completion and auto-formatting. But besides that, I think that altering the syntax in such a way doesn't make sense. It's in effect rewriting the language spec, and for no benefit other than to make it feel like another language. You're also stuck with two bad choices:
|
I do feel a bit like this issue is like asking that English speakers stop conjugating "be". Doing so is technically wasteful of mental facilities, but not doing is makes communication significantly more difficult as people are forced to adapt; and there's a huge existing library of content using the old style. |
@whoisj If you want to stop conjugating verbs you learn an Eastern language like Chinese, Japanese, Thai, Vietnamese, etc. You don't change English. 😀 |
From http://en.wikipedia.org/wiki/Don%27t_repeat_yourself
VS provides tools to C# programmers that are triggered by default at the end of every block when you type |
@gafter The cost of repetition depends on its form. From most to least expensive:
C# auto-intending provides form 2 or 3, depending on your IDE. By way of comparison, Entity Framework Model First uses form 3 and Code First uses form 5. Granted, braces are much lighter than generating entire classes. However, it's nice to eliminate the experience of 4 or 5 cascading braces at the bottom of a C# file that you know has correct indentation but doesn’t yet have the braces right, and you play guess and check adding or removing braces until the compiler or IDE tell you the brace syntax is valid, i.e. you’ve succeeded at repeating your indentation logic. |
The largest cost of using braces and semicolons to repeat indentation structure is the vertical whitespace. This cost is significant, which is why, as @sharwell commented, C# is working to reduce unnecessary vertical whitespace with getter-only auto-properties and expression-bodied members. If those features eliminate 10% of non-value add brace lines, why not go for the other 90%?Additionally, there is benefit to not fuddling with braces when the IDE doesn’t happen to do quite what you want. Coding isn’t a linear exercise. Per @HaloFour’s comment, you can move the indicator of whether indent is significant from the project level to the block level by requiring a colon before blocks with significant indentation. This would let you integrate the two syntax styles in the same project and even file. An IDE could aggressively auto-format to mitigate the risk of confusion. However, I don’t see the value in mixing the two syntaxes. Because they map directly from one to another, an IDE can auto-convert an entire codebase when the project syntax mode changes. Similarly, it can auto-convert pasted code, which makes it easy to use old code samples from the web. |
And if the person forgets the colon they will inadvertently screw up scope My comment is to further indicate why this is a horrifically terrible
|
@HaloFour, I would suggest you check the comment history more carefully. Despite the fervor with which you have repeated (ironic, given the topic) your favored approach to this issue, the two compiler team members have wisely expressed neither agreement nor disagreement with it. Language feature selection and definition is successful after careful contemplation of the many facets of the issues and its design tradeoff. As you reread, you will also discover that your repeated concern about missed colons causing inadvertent scope are addressed by (a) not introducing colons and (b) even if you did, having IDEs autoformat so that the scope is clear. And if that’s not enough, I’d add a (c) that the compiler could issue a warning if the indentation is fishy – but really, you could just stop at (a). |
@breyed Repetition is a form of emphasis. If you can read the comments of the three collaborators who have been willing to post to this thread and find a positive (or even neutral) takeaway then I have to applaud your optimism. You could also stop at (a) by using one of the several existing languages targeting the CLR which have whitespace-sensitive scoping, some of which having actually been written by Microsoft. (b) makes the entire discussion moot, the IDEs are already performing the indentation, YOU don't have to repeat anything. The fact that the language might, based on some optional conventions, is entirely irrelevant, when the tooling provides built-in mechanisms for avoiding this. |
I read most of this thread and accept the premise that C# isn't DRY with regard to the assertion of the original poster. The severity of the issue isn't significant enough to have it be corrected by any of the existing proposals. It will just add yet another concept that one has to learn to understand the language. The only acceptable way I think thus can be addressed in the future is some ingenuous way of introducing metaprogramming such that this and many other constructs can be adopted. That may never happen. Kenneth Kasajian -- Mobile call or text: 949-288-3717, Skype: kkasajian
|
One thing that I'd like to see is a lot more experimental forks of the language so people can actually see and play with these changes rather than just discussing it in the abstract. Howe can we get more people to feel comfortable with and attempt to actually implement / prototype the language features they want? That'd be cool. |
Significant whitespace for blocks is pretty much always wrong. Since text is the fundamental medium used to transmit the data to the tooling making tools depend so much on position in this way isn't a good idea. What happens if you have to past code into an email form for a mailing list or are reading an article and your browser doesn't pickup on the spacing used by an author? I have had this happen when trying to learn Haskell, seriously it isn't fun. That we use fancy editors to write code is not in fact a justification for creating grammars that require specialized tools just to use without pulling your hair out. It isn't even good UX when you start thinking about what happens if someone uses large fonts and can't even see indentation levels. |
I know more than a couple of developers who also prefer using non-monospaced fonts. One insisted that anyone not using Tahoma as their font in Visual Studio was barbaric. |
Proportional fonts are generally great for coding. You get more horizontal real estate and centuries of typography benefits. I personally prefer Calibri. A trade-off of using a proportional font is you can only align text based on indents, although with refactoring even with non-proportional fonts suffer if you rely on in-line alignment. Regardless of the font, space sizes are proportional to non-space sizes, so large fonts shouldn't pose a problem. |
I'm actually thinking more of zooming rather than simply choosing a physically large font. |
Just came across this discussion. I have to say that if an alternate syntax were added to C# I would have to abandon it wholesale. What a bad, bad idea. I also find the idea that indentation/braces/whitespace falls under DRY to be just absurd. |
Closing as this is not actionable... but you're welcome to continue commenting here |
@breyed why not just pick up F#? It's quite easy to learn. |
C# indentation and use of curly braces should not change, even if you could switch it on or off; it's not a good idea. |
@panesofglass If I hadn't already learned languages like F# and Python, the repetition in curly braces languages may not have occurred to me. F# in particular is an excellent language; however, C# makes more business sense sometimes because of better tooling, framework integration, and developer familiarity. The advantages of C# were what prompted me to raise this issue to explore whether braces are inherent to the language or whether a indent scoping could make it even better. |
In my opinion the indentation requirement in F# and Python are weak points rather than strengths. |
Keep braces and semicolons. Close this discussion. |
Already closed as not actionable in #2974 (comment) ... but anyone who wants to is welcome to discuss it. I'm unsubscribing now. |
In C#, the curly braces and indentation provide redundant ways to express the structure of namespaces, types, statement blocks, etc. Only the braces are normative, but if the indentation doesn't match, it confuses people. To compensate for the need to repeat ourselves, we use coding guidelines and tools to enforce the pairing.
Of course the redundancy intentional, going way back to C. It allows unusual whitespace patterns for the rare circumstances where they are useful. Perhaps a whitespace-ignorant parser was simpler to write on the memory constrained computers of the 1960s.
In any case, the lack of DRYness is a design hole that - while consciously carried forward - is fixable. A great solution would be to take page out of F#'s book and retain the existing curly-brace syntax as the verbose syntax and introduce a new whitespace-based lightweight syntax.
The text was updated successfully, but these errors were encountered: