Being Cellfish

Stuff I wished I've found in some blog (and sometimes did)

Beginners should not use LINQ

Change of Address
This blog has moved to blog.cellfish.se.

Beginners should not use LINQ

  • Comments 12

When I first heard of LINQ I got really scared. I could see that it was a very powerful tool but also a tool that would be easy to abuse. Most experienced developers tend to agree that putting SQL statements into your logic or even GUI code is a bad design. Beginners tend to realize this pretty soon too. But with LINQ we get the opportunity to do the same kind of bad design once again. And since it is ".Net code" rather than "SQL statement" I had a fear that it would take longer before the beginners learned their lesson. And why do I care? I don't know. Guess I'm just one of those guys who want everybody to do a good job.

Since LINQ was introduced I have not really seen LINQ in action very in any real code so I kind of forgot about this. But then I read this. Looks like I was right. LINQ is being abused just in the way I feared. But I'm happy to see that a person who I've heard speak warmly about LINQ so many times finally points out how LINQ can be your gate to bad design. And remember to read the comments too when you follow the link above. The topic unfolds...

UPDATE: Not only did the topic unfold in the linked thread. It unfolded here. If you just found this page I strongly suggest you read all the comments.

  • Respectfully...

    I completely disagree: beginners *should* learn LINQ.  Beginners *must* learn to write maintainable code, and LINQ -- to anything -- is one of the best ways to writing short, exceedingly maintainable code that does precisely what you think it should.

    There is zero difference, maintainance-wise between using methods on an in-memory domain model and using methods on an IQueryable.  None.  The code is precisely the same.  Done propertly, the UI doesn't even know what's underneath an IQueryable.

    There are an unfortunately number of entrenched, nigh-cultish alpha geeks needing to rethink design in a world where you're not passing around some string being cobbled together into a SQL statement.  That is the source of problems in the old world and why DALs came into being.  But, using LINQ to SQL, that situation does not exist and the old cautions do not apply.

    Think first about why design dogma came into being before making such broad statements about what is right and proper for beginners.

  • I not fully agree with your opinion.

    First, a beginner or a bad developer will always write bad code whatever the language and the plateform. LINQ is no more dangerous than operator overriding, interfaces or any "smart" language feature that are necessary (no professional software can today be developed using MS interpreted Basic of the 70's...).

    Secondly I think you're making the mistake a lot of people is making: LINQ is definitively NOT a database technology. LINQ To SQL or LINQ to Entities are just two flavours of LINQ. LINQ To XML, LINQ to Object, LINQ to Datasets, etc are not linked (directly) to any database. Thus, LINQ is NOT SQL in any way.

    At first glance it "can" look like a "kind of" SQL. But it is a very (very, I said very ?) limited sight of what LINQ is really.

    So, I would say that every beginner must learn and practice LINQ because a good C# 3.0 code is made of LINQ for everything (listing files in a directory, knowing which process is using the most memory, looping through controls on a forms to init them, etc, etc...).

    Of course, C# 3.0 is far more complex to master than C# 1.0, it is more subtle, it allows for more smart code. That's the core of our job : learning and learning again the new technologies, new languages, new plateforms !

    Farther I'll say that someone, even a beginner, that can't understand and learn LINQ (like any C# 3.0 additions) must change its job plans and look for something easier, plumber, butcher or some manual job (and valuable, I'm not saying at all those profession are "less" interesting or "less" valuable. The world is needing all talents).

    So, LINQ can lead to bad design as any other C# 3.0 features. Wanting to see LINQ as something that can be ignored, as a "plugin" is not the right way to see things : LINQ _is_ C# 3.0 like lambda expression or anymous types.

    You can't say you're a professional if you plan to use just the features of C# 3.0 that make it looking like interpreted Basic of the 70's...

    I really think you must reconsider your point of view about LINQ. Sincerely.

  • I did not say beginners should not learn LINQ. And everybody should learn to write maintanable code. So far I guess we both agree.

    As mentioned among the comments made the linked post; if you start using LINQ to SQL everywhere in your GUI code you get a maintanablility problem since you'll end up with redundant code all over your application. Knowledge about the database design will be in more than one place and that is bad. The database design evolve and eventually change rendering some queries invalid.

    The problem is not that beginners learn LINQ. The problem is that beginners are more likely to end up with a duplicate code and a bad design since they may feel that LINQ to SQL is OK in a place where T-SQL strings are not. But in reality they are just as bad.

    I also thought the current title made this post a little more interesting than if I had called it "beginners should not write code with a bad design"...

  • @odhan:

    I can agree that I probably should have been more clear from the beginning that it is LINQ to SQL that is my main concern. On the other hand I thinkthis is the most common use of LINQ by beginners.

    "Beginners should learn LINQ but be careful use LINQ to SQL since it is a risk they use it wrong and end up with a bad design" would probably have been the best title for this post.

    And you're completly right that LINQ is not the only powerful tool that can easily be abused and used to create a bad design (some people don't even need fancy tools to create bad designs). So I guess I have a whole new list of posts I must make. There are lot of things beginners should not use until they fully understand their consequenses. :-)

    On a more serious note. If a beginner does not use these tools, how can they learn them? Experiment! Talk with more experienced developers. Learn from others with more experience. Soon you're no longer a novice and start using the tools in a good way. And then I'm happy...

  • I agree, ofcourse :) While, as stated in the comments, a well managed solution with IQueryable will hide the storage details it is still important to honor old design principles like DRY ( Don't Repeat Yourself) and Separation of Concerns. They apply even to solutions with LINQ.

    As I state in my post; LINQ is still a query language, although typed and integrated with C# / VB, and queries as such have a place in the application design. You shouldn't spread it all over your applications. Maintainability will be a mess.

    I also don't agree that it's the nature of T-SQL strings that drive forth the design pattern to use DAL's. It's there because Separation of Concerns is important and that principle applies to all your development. Don't mix cache code with databinding, don't mix data access with bussiness logic, don't mix bussiness logic algorithms with event handlers, and don't mix query syntax with other kinds of code.

    As Robert C. Martin states, a module should have /one/ reason to change.

  • Oh and, of course beginners should learn and use LINQ, but as with any other technology they should properly learn it with all the best practices and design principles there.

  • Patrick, cellfish:

    You fail to state how LINQ to Objects differs from LINQ to <some IQueryable, or any other> in terms of maintainability.  If you accept the first, how would you justify denying the second?

    Relying on Martin, Fowler, or any of their works -- which may have been perfectly valid (and I'd certainly agree in Fowler's case) informative in the past -- does not much bolster your argument for the present.  The approach LINQ takes means that a module does *not* have to be changed just because something underneath has:  this was one of the primary motivations for LINQ to begin with.

    If you want to insulate yourself from changes in the shape of the data you get back from your data source, there are perfectly LINQ-ish ways to do that.  LINQ to Entities, for example, is designed specifically with that in mind in the case of relational databases.  

    So I don't think there is any validity in saying "Thou shalt completely barricade thy UI from LINQ to SQL.".  Indeed, I think that's an entirely self-limiting inertia that kills any actual progress toward solving the true problem.  We already have sufficient abstraction (in the form of IQueryable and IEnumerable) that UI, etc are protected.  If you find yourself in a situation where the underlying data model needs to shift independently of the application's view, then the answer doesn't lie in fearing LINQ -- it lies in changing which LINQ provider you make use of (eg, LINQ to Entities, or some other mapping technology).

    There is one thing I would support in LINQ to SQL:  a minimal layer that only *instantiated* a data context, and instead of exposing Table<T>, exposed IQueryable<T>.  Feel free to pass around the IQueryables, because they will save your application's perf without stringing spaghetti all over.

    And that is what I'd teach -- not fear of LINQ to SQL, or even fear of LINQ in a UI, but awareness of how to use LINQ such that you can change technologies without losing LINQ's ability to, for example, push those UI operations (sorting, paging, etc) back to the data source, where they belong.

  • @kfarmer:

    The difference is small and the reason LINQ to "omething other than SQL" is that since it is not SQL I believe the risk of using LINQ as a replacement for SQL is smaller thus reducing the risk of a bad design because of a newbie misstake. For me it is the resemblance between SQL och LINQ syntax that is the danger here.

    Interesting that you mention a minimal layer providing abstraction. That is an important aspect for me in this case since that layer of abstraction probably is enough to achieve a reasonable level of maintanability. Naturally depending on how that is implemented and used.

    Interesting also that you mention application performance. I'm a strong believer that "premature optimization is the root of all evil" and that is why I refrain from choosing a design for performance reasons if there is a better design from a maintanability perspective.

    Last I must disagree that IQueryable and IEnumerable are suficient abstraction for the UI in them selfs. For me it is not the interface it self that defines level of maintainability. It is rather how that IQueryable is obtained. Usually you want to select data using some kind of filtering and these properties (whatever they are) often turn out to be of "magic values" for the GUI. They are strings and values that "just have to be something" in order to make the query work. In these cases I think it is bad to have those magic values in the GUI. If you however use LINQ in the GUI to query the service facade for a number of business objects, I personally don't have a problem with that if it is done right. The reason for my initial post on this topicis that I think it is hard, especially for beginners, to make that call. And if it is hard I think it is better to go for a safe bet instead of confusing the beginner.

  • "safe bet" vs "confusing the beginner" .. I don't buy that argument, on the basis that I don't buy either the former or the latter as following from your prescription.

    The safe bet is going to the be the bet that produces the simplest code.  I've seen more confusion arising from trying religiously to adhere to outdated thinking -- particularly wrt this very topic -- than in simply doing the direct, maintainable solution.

    My devs are currently in the midst of finishing a set of moderately complex data browsing controls.  Using LINQ, specifically using IQueryable including LINQ to SQL, our beginners (read, graduated a few months ago) are better able to understand what's going on and why, than they would using the sample code that was handed to use, which was afflicted with unnecessary abstractions.  The code has no "magic values" and, indeed, they are now able to create their own expression types.

    As high an opinion I may have of their abilities, I hardly think they are of any unique calibre, especially since I've seen the same with others.  To be honest, the folks I *have* seen having difficulties in understanding what's going on in LINQ (to anything) are generally those senior devs who've spent all their time stuck in the old ways.  That alone speaks much more loudly to me than fears about what beginners may or may not do.

  • It just sounds to me that your beginners have good mentors. Or did they come up with how they were going to design the component all by them selfs (not only in regard to the use of LINQ)?

    I'm still not yet convinced that LINQ is like any other tool in the dev box. I hope you can agree with me on one thing: With LINQ to SQL you can write code that is just as bad as having a string of SQL in your code. If you can agree on that I hope you also can agree that the nature of LINQ is that it is code. And since it is code rather than a string of SQL a novice might think "strings of SQL is wrong but this is OK since it is code. LINQ is my DAL".At least it is a larger risk of that thought crossing their mind since it is code and not the well known "SQL string in code"-pattern. It might be harder to recognize that this is the same thing for a novice programmer (maybe that is only a problem for poor novice developers).

    That is my point. And I'll leave the "LINQ has nothing to do in the GUI" part for Patrik to sort out because I do not feel as strong about that.

    I also think you have a valid point that young(er) people have a tendency to grasp and pursue new technology more easilymany times actually I find it really interesting that you've experienced that those persons use LINQ in a better way than the more experienced developers. I will definitly try to see that for my self and reevaluate my position on this topic.

  • @kfarmer: IQueryable is not a sufficent abstraction. LINQ is still a query and should be handled as such. Queries change, queries need to be maintained and thus they should do so in a separate layer, as any other part of your application.

    With that said, IQueryable is not really that innovative. What's innovative is how the compiler handles the magic that goes with it. The patterns that IQueryable follows has been around for years but without the slick language integration that it now got.

    LINQ doesn't change how applications should be written, it just makes querying a little easier. Basic software engineer principles still apply and one of those principles is Separation of Concerns which bluntly led to the idea, amongst other, that UI's should not hold any logic but that needed to present. Querying, no matter what you query in-mem or database, is not part of the UI responsibility and should not be there.

    Or are you arguing that basic layering and separation of business logic and algorithms no longer apply because "LINQ" will take care of that?

    No my friend, LINQ is about querying not a paradigm shift. Querying made simple and partly abstracted away from the source I agree, but it still is querying, you still need to follow the basic principles of software engineering that has been around for 40+ years and survived all new technology breakthroughs.

  • BTW, I am pragmatic, If all you got is a couple of queries and one or two classes, the basic YAGNI rules apply as well of course. But for any major system you don't want to mix responsibilities, no matter what kind of slick technology support you got.

Page 1 of 1 (12 items)