How to make your code completely unreadable with .NET 3.5

18 בנובמבר 2007

12 תגובות

[This blog was migrated. You will not be able to comment here.
The new URL of this post is http://khason.net/blog/how-to-make-your-code-completely-unreadable-with-net-35/]


With the time we got our developers less and less professional by enhancing programing languages and using easier code syntax. However, while we are trying to make things better, we discovered that things are going bad. Let's see following code sample



delegate string BringBeerDelegate(int amount);


static void Main(string[] args)
        {
            Console.WriteLine("Bringing beer using anonymous delegates");
            AskBarmenAboutBeer(2);


        }


static void AskBarmenAboutBeer(int amount)
        {
            BringBeerDelegate bringBeer = new BringBeerDelegate(BringBeer);


            Console.WriteLine("You got {0}", bringBeer.Invoke(amount));
            BringAnotherBeer(bringBeer, amount+1);
        }


static string BringBeer(int amount)
        {
            return string.Format("{0} beers",amount);
        }


static void BringAnotherBeer(BringBeerDelegate firstPint, int newAmount)
       {
           string res = firstPint(newAmount);
           Console.WriteLine("You got another {0}",res.ToString());
       }


It pretty clear what this code is doing. It creates new delegate named BringBeerDelegate, that actually formats string. Then it invokes the delegate. After it the delegate transferred into BringAnotherBeer method and invokes there. This way it works in .NET 1.1 So far, so good. Let's use anonymous delegate, introduced in .NET 2.0 instead on using method to invoke it. Now, we'll add another method, that creates and invokes the anonymous delegate BringBeerDelegate.



static void AskBarmenAnonymouslyAboutBeer(int amount)
        {
            BringBeerDelegate bringBeer = delegate(int am) { return string.Format("{0} beers", am); };


            Console.WriteLine("You got {0}", bringBeer.Invoke(amount));
            BringAnotherBeer(bringBeer, amount + 1);
        }


Now, calling AskBarmenAnonymouslyAboutBeer with number of pints we want, we'll create and invoke the anonymous delegate. The code less readable (as for me), but never mind, we saved a couple of code lines.


Now, let's write following:



BringBeerDelegate bringBeer = am => string.Format("{0} beers", am);
BringAnotherBeer(bringBeer, ++amount);


What the hell all those => are doing? This is anonymous delegate BringBeerDelegate defined by lambda¹ expression.



small lyrics: ¹Lambda (uppercase Λ, lowercase λ) – the 11th letter of the Greek alphabet. In the system of Greek numerals it has a value of 30. Letters that arose from Lambda include the Roman L and the Cyrillic letter El (Л, л).
Lambda expressions provide a more concise, functional syntax for writing anonymous methods.


Is it really more concise and functional syntax? What do you think, following code doing?



Func<int,string> firstTime = (int am) => { return string.Format("{0} beers", am); };


Func<T..> is generic delegate type for lambdas. That's piece of cake, isn't it? Let's see you to predict what following code will output…



BringBeerDelegate bringBeer = am => string.Format("{0} beers", am);
Func<int, BringBeerDelegate, string> bringBeerFunc = (int am, BringBeerDelegate beer) => { return beer(am); };
Func<int, Func<int, BringBeerDelegate, string>, string> lastTime = (int am, Func<int, BringBeerDelegate, string> func) => { return func(am, bringBeer); };


The other awful thing in new .NET 3.5 is anonymous types. So, great news, VB programmers, there is new king in the village. His name is VAR. Following previous code section, following make our life even more complicated.



var whatBeer = bringBeer;


//At least, either compiler and interpreter knows, that whatBeer variable is of BringBeerDelegate type


image


Happy and very unreadable coding, my friends.


Source code for this article.

הוסף תגובה
facebook linkedin twitter email

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *

12 תגובות

  1. Thomas18 בנובמבר 2007 ב 21:33

    You're kidding right?

    Those has got to be the worst examples of using the new features to make code elegant, instead using them to make it awful.. Good job not at all getting the point.

    הגב
  2. עומר ון קלוטן18 בנובמבר 2007 ב 21:53

    I disagree. I think that once you get used to the syntax and don't abuse it, it's pretty a powerful shorthand for what would otherwise have been quite cumbersome.

    There's always the problem with abuse. I follow these rules:
    http://weblogs.asp.net/okloeten/archive/2006/07/10/Lambda-Expressions_2C00_-Anonymous-Methods-and-Methods.aspx

    הגב
  3. Tamir Khason18 בנובמבר 2007 ב 22:02

    Thomas, Omer
    Maybe I'm rather oldfasion, but I'm really think, that programming language should be readble and elegant. We are not printing code on paper, so we should not care about saving trees. Using "power shorthand" syntax is not always good thing, especially, when dealing with programmers, who know what they are doing.
    But, it's, as always, only my humble opinion 🙂

    הגב
  4. Niki19 בנובמבר 2007 ב 0:16

    Your point seems to be, if a feature can be used to write code that's hard to understand, then the feature is bad. Is that right?

    Wouldn't it make more sense to learn those new programming language elements, and see how they can be used to make code more readable?

    BTW: Maybe you should have a look at languages that are usually regarded as "elegant", like Lisp, Python, Ruby, Haskell or ML. Guess what? They all have lambda expressions!

    הגב
  5. jhunter19 בנובמבר 2007 ב 7:57

    I agree with you, I hate anonymous types. I expect to frustrated when I start reading people's code in .net 3.5.

    הגב
  6. Tamir Khason19 בנובמבר 2007 ב 9:59

    Niki, no it is not my statement. My statement is that we are studing developers to write bad code, by adding more and more unnessesery features to the programming language.
    In Python 3000, for example is was decided to remove lambdas from the language and replace them with anonymous delegates. Regarding Ruby, delegates works as block expressions. They are working very hard to add delegate support to the language += and -= expressions.
    So, are you really thinking , that lambdas are good? 🙂

    הגב
  7. Angelos Petropoulos19 בנובמבר 2007 ב 16:47

    I agree with the point you are trying to make. My feelings are reflected by this post on LINQ (the reason anonymous types and lambda expressions were implemented) that I made only a few days ago …

    http://www.angelosp.com/blog/post/TechEd-Wisdom-%e2%80%93-Still-not-convinced-about-LINQ.aspx

    הגב
  8. Niki20 בנובמבר 2007 ב 16:44

    I just have to reinstall VS2008 because I keep getting weird "unexpected errors" (very helpful error message, by the way. thank you, microsoft!). So I have a few minutes to write down a reply:

    > Niki, no it is not my statement. My statement is that we are studing developers to write bad code, by adding more and more unnessesery features to the programming language.

    That's your conclusion, but I still don't see how you get to that conclusion. Yes, of course, the feature is kind of redundant, but not more redundant than for-loops, foreach-loops, do-while-loops, events, switch-case or properties are. Yes, there is potential for misuse, but IMHO you can do far more damage e.g. with events, which can lead to serious spagetti code.

    I see two possible conclusions out of this, either:
    a) Use a minimalist language like Scheme, that does not have all those redundant features. I like Scheme, but unfortunately I'm quite alone with that, most companies seem to prefer "rich" languages. (And guess what: Yes, Scheme does have lambdas…)
    b) Teach your programmers to use the features of the language wisely, not to obscure the meaning of the code they're writing, but to clarify it.

    > In Python 3000, for example is was decided to remove lambdas from the language and replace them with anonymous delegates.

    I think I read a statement from Guido van Rossum (the man behind Python) that lambdas will stay in the language, but that might be outdated. Anyway, the reason why there's discussion about lambdas in Python are largely syntactic: they simply don't fit into the indentation-oriented block structure. That's not a problem that in C#.

    > So, are you really thinking , that lambdas are good? 🙂

    Yes, of course I do. Why? For one thing, I have some mathematical background, so I've found lambda calculus intuitive long before anyone thought C# might get lambda expressions some day. Also, I know a bit of higher-order-programming, and know how much it can simplify development if used correctly. And I can think of code like this:

    purchases.SortBy(p => p.Price);

    I don't see how I could make this code any clearer. In .NET 1.1 (or in C++), I would have a static function like "GetPrice" somewhere far aways form the SortBy-call, which is of course bad because it destroys code locality. In C# 2.0, I could to do something similar with an anonymous delegate, which does the same thing, but makes the code hard to read, because it is far more verbose, and also less flexible, because it cannot be used as an expression. (I am hoping that anonymous delegates will be removed in some future version of C#.)

    הגב
  9. Tamir Khason20 בנובמבר 2007 ב 17:12

    Niki,
    I understand you'r statement. However, how many production code wrote, by using Scheme? It's really cool academic appropach, but still it's very far away from being production.

    I have neither time nor wish to teach programmer. I believe, that those, who want to write code, must understand what they are doing and not be "code monkeys".

    purchases.SortBy(p => p.Price); statement is very very expressive, however, I am not speaking about "simple patterns". Let's imagine, that p.Price is not number, but object with locale formatting. Can you imagine how your code will work? Can you know if in your statement sorting will be ascended or decended? You can not.

    I'm oldfashined, so I think, that events are bad, 'cos they are much worth then system messages. And that's exactly my point. 🙂

    הגב
  10. Niki20 בנובמבר 2007 ב 18:03

    > I have neither time nor wish to teach programmer. I believe, that those, who want to write code, must understand what they are doing and not be "code monkeys".

    I would agree to that, but then your problem vanishes anyway: if programmers know what they are doing, then they won't produce cryptic code like the "bad example" code in your article. If they do anyway, they should be slapped around the head and forced to do maintainance programming for at least a year.

    > purchases.SortBy(p => p.Price); statement is very very expressive, however, I am not speaking about "simple patterns". …

    Me too: You wouldn't need lambdas for "simple patterns". But the more complex your task gets, the more helpful lambda expressions will be.

    > Let's imagine, that p.Price is not number, but object with locale formatting.

    Yes, let's: What options would you have then? You could:
    – write your own sorting routine that uses the right comparison function (bad, lots of duplicate code)
    – Use a compare-function-pointer (as in C's qsort or C++'s sort functions) or a delegate pointing to a static function. (bad, violates code locality.)
    – Use an anonymous delegate (not that bad, but verbose; and delegates are a redundant feature, so they will (hopefully) go away some day.)
    – Or, in C# 3.0, you could finally use a simple lambda expression:

    customers.Sort( (l,r) => l.Name.Compare(r.Name, Globalization.CultureInfo.SomeWeirdEuropeanCulture);

    הגב
  11. aL5 בדצמבר 2007 ב 3:35

    did you proof read your post at all..? thait has to be the most poorly written thing ive read in a long time..
    ok fine, i can get over the grammar but your example of a "bad" lambda is just silly.. first of all you ask if i the reader can predict what the code:

    BringBeerDelegate bringBeer = am => string.Format("{0} beers", am);
    Func bringBeerFunc = (int am, BringBeerDelegate beer) => { return beer(am); };
    Func
    , string> lastTime = (int am, Func func) => { return func(am, bringBeer); };

    will output. well yes actually, i can.. not a damn thing. you never call lasttime so it wont output anything. its an unrealistic example anyway because you declare several arguments that you never use.

    and your bash on the var keyword? there isnt even an argument as to why it will make your code unreadable!

    you dont seem to know very much c# and that whould explain why you seem to claim most language features that differs from c are "unreadable"

    i'll never visit this blog again so you can flame me all you want. but you should know that your laughable examples and your apparent complete ignorance of the workings of c# makes for an awfully unprofessional blog.. atleast in the context of c#.

    the horrible english doesnt help either

    הגב
  12. Tamir Khason5 בדצמבר 2007 ב 9:07

    aL,
    1) I'l not. Actually, I never proof read my posts. I just write – this is my way of writing blog 🙂
    2) Instead of writing "I can predict", just predict it 🙂 BTW, it uses all arguments there.
    3) Regarding C#, you are right, I do not know C#, as well as I'm not programmer at all – here the proof http://blogs.microsoft.co.il/blogs/tamir/archive/2007/11/18/70-552-should-be-removed-or-at-least-changed.aspx
    4) You are not have to read my blog, really, you dont, 'cos I'm awfull unprofessional in any context and my english is bad

    הגב