Extension Methods - Satan's favourite construct (controversial to nerds)
-
I partially agree with you, but it can be useful if used with care. Bad programmers will find ways to screw up good design despite the language and its features. One of my favorite rants is the abuse of
var
. While it can save you a lot of work when defining anonymous types, some people simply usevar
everywhere, making some pieced of code very hard to read and understand. Having said that, I use some extension methods when I need just that extra functionality of a type defined by the framework that I don't have access to. Example: I usually define enumerators to be used as members of some classes. Say:enum OperationType
{
[Description("Cash Withdraw")]
CashWithdraw = 0,
[Description("Money Transfer")]
MoneyTransfer = 1,
}Now, The text on the description attribute allows me to have the enum value user viewable if I want to populate a dropdownlist with it's possible values. Overmore, I can even refer to variable on a resource file to make it localizable. Now, in order to fetch this description that is user friendly/localizable I simply define an extension method that makes my life a whole lote easier:
public static string GetDescription(this Enum enumToRead) { if (enumToRead == null) return string.Empty; Type type = enumToRead.GetType(); MemberInfo\[\] memInfo = type.GetMember(enumToRead.ToString()); if (memInfo == null || memInfo.Length <= 0) return string.Empty; object\[\] attributes = memInfo\[0\].GetCustomAttributes(typeof(DescriptionAttribute), false); if (attributes == null || attributes.Length <= 0) return string.Empty; return ((DescriptionAttribute)attributes\[0\]).Description; }
Of course, a lot of language sugar candy can be abused, but that is the programmer's fault, not the language. But I confess that I sometimes do regret that the
var
keyword was ever introduced.To alcohol! The cause of, and solution to, all of life's problems - Homer Simpson ---- Our heads are round so our thoughts can change direction - Francis Picabia
-
Naerling wrote:
How is that any worse than using SP's in your database (which to me are king of like black boxes since they're out of your code) and/or strings in code?
Because there are some tasks that one cannot do via SQL. Or at least cannot do it efficiently and/or without writing the entire SQL block (not statement) in the string. Not to mention of course that SPs can act as a database layer in the database just as one might have a database layer in C# and for much the same purpose given that the database in in fact a separate server.
Naerling wrote:
Furthermore when using LINQ to SQL or LINQ to Entities you get a bonus of moving your queries from in-code strings
Of course the down side of that can be that some developers do not know or prefer to ignore that some tasks should not be done in the client. Thus they create LINQ rather than using a SP.
Naerling wrote:
and easy to read LINQ queries.
That of course is entirely subjective. Like any code it can be written in form that is in fact hard to read. And without code reviews whether it is in in fact "easy to read" is likely nothing but a rationalization by the author. Which one can say about any language.
if (arguments.All(a => a.MakesSense))
{
Console.WriteLine("That is so true!");
}Output: That is so true! Of course LINQ shouldn't always be used to replace the SQL part from a database, but it sure makes it easier!
It's an OO world.
public class Naerling : Lazy<Person>{
public void DoWork(){ throw new NotImplementedException(); }
} -
Sometimes I yearn for a return to .NET 2.0. The C# that came with it was a great language and now that generics were included it was essentially complete in my mind. Since then, they've been adding all sorts of dubious things to the language LINQ being the most notable but now we also have the async/await business which really is anything but the simple solution to asynchronous programming they tell us it is. Extensions methods, everyone's favourite encapsulation anti-pattern debuted with LINQ in order to make it work and some people (me) viewed them with suspicious eyes at the time but didn't really know how bad things could get. Having recently worked on a system where they have been abused to the fullest I can tell you. You start off with pretty hollow objects with very little in the way of methods, just enough to get at the data. Then, you put all your logic in extension methods, preferably in different assemblies. A sort of warped onion architecture. Now, any normal developer who goes looking for a type's methods won't find them in the type or even that assembly. A missing reference will make them disappear completely. Also, with careful planning, you can make it exceedingly hard to move that logic back where it belongs because doing so will cause all kinds of circular dependency issues. Immutable code! Shocking stuff, but if you really hate the world, don't forget the Action<> and Func<> delegates. These are useful because you can avoid passing meaningful data to methods. Instead just pass delegates everywhere (a functional programming approach I'm told). This makes it practically impossible for anyone to work out the execution flow by examining the code. Combine the two and you have one thoroughly malevolent system. People bang on about patterns all the time in software development, but if you ask me (I'm aware you didn't) the way to build a good system is to always, always, always keep everything as simple as you can make it.
Regards, Rob Philpott.
One of our wise sage developers here has the following quote about extension methods: "Extension methods feel like you're having an affair..." That just about sums it up. :laugh:
-
Naerling wrote:
LINQ is a great tool which can make code easier, more flexible, better maintainable and more readable
X is a great tool which can make code easier, more flexible, better maintainable and more readable. That hard part of that statement is finding any software technology X where that statement was never made.
Naerling wrote:
I've seen horrors in .NET 2.0 (pre-LINQ) you can't even begin to comprehend.
I have seem messes in every technology that I have ever encountered. Including hardware.
I completely agree with you. I like LINQ a lot, but I've seen messy LINQ queries too. As I like other technologies which have been abused. Then there are technologies I generally dislike, but that helped me out in rare occassions. That's why I disagree with the OP. Sure LINQ and .NET 4.0 has its flaws, but many good stuff too. Why want to go back to .NET 2.0? .4.x has everything and more and .NET 2.0 can be just as messy, and perhaps even messier!
It's an OO world.
public class Naerling : Lazy<Person>{
public void DoWork(){ throw new NotImplementedException(); }
} -
Sure yeah, anything can be abused to the point where it's no longer awesome. Even sex with supermodels gets old after a while :)
Jasmine2501 wrote:
Even sex with supermodels gets old after a while
:laugh: That's why now I only go out with girls of non conventional beauty
To alcohol! The cause of, and solution to, all of life's problems - Homer Simpson ---- Our heads are round so our thoughts can change direction - Francis Picabia
-
jelamid wrote:
If you are working for someone else it it this attitude that causes the most grief for the business. Which is the situation that the OP is in. In this case it is not your code base, you have no control over who sees it next, and you will collect bad karma as those who follow will curse your name. :)
Ahhh you may be missing my entire point and/or may not be familiar with Extensions. The
ForEach
extension forIList
which is within the "System.Linq" namespace is common knowledge for programmers using the .Net Framework 3.5 and up. Er it should be. And my point is, if it is not then you need to do some homework before touching a system built on that framework. I chose the ForEach extension onto theIEnumerable
because of this reason. It should be understood and if it is not that means you lack the basic understanding of extensions which were added multiple frameworks ago. That is not my problem nor should it be. If the business chose/authorized the use of a framework it will be used. If the management then assigns inappropriate resources (i.e. someone that lacks the basic knowledge of the framework) to the code base that is managements fault (or the resource not fully disclosing their actual understanding), not the original developers fault.Computers have been intelligent for a long time now. It just so happens that the program writers are about as effective as a room full of monkeys trying to crank out a copy of Hamlet.
I hear crickets...
-
I hear crickets...
-
jelamid wrote:
If you are working for someone else it it this attitude that causes the most grief for the business. Which is the situation that the OP is in. In this case it is not your code base, you have no control over who sees it next, and you will collect bad karma as those who follow will curse your name. :)
Ahhh you may be missing my entire point and/or may not be familiar with Extensions. The
ForEach
extension forIList
which is within the "System.Linq" namespace is common knowledge for programmers using the .Net Framework 3.5 and up. Er it should be. And my point is, if it is not then you need to do some homework before touching a system built on that framework. I chose the ForEach extension onto theIEnumerable
because of this reason. It should be understood and if it is not that means you lack the basic understanding of extensions which were added multiple frameworks ago. That is not my problem nor should it be. If the business chose/authorized the use of a framework it will be used. If the management then assigns inappropriate resources (i.e. someone that lacks the basic knowledge of the framework) to the code base that is managements fault (or the resource not fully disclosing their actual understanding), not the original developers fault.Computers have been intelligent for a long time now. It just so happens that the program writers are about as effective as a room full of monkeys trying to crank out a copy of Hamlet.
Collin Jasnoch wrote:
The
ForEach
extension forIList
which is within the "System.Linq" namespace is common knowledge for programmers using the .Net Framework 3.5 and up. Er it should be.And that namespace is more important than any of the other hundreds (thousands) because?
Collin Jasnoch wrote:
if it is not then you need to do some homework before touching a system built on that framework.
Sounds reasonable.
Collin Jasnoch wrote:
I chose the ForEach extension onto the
IEnumerable
because of this reasonI see absolutely no connection there. IEnumerable belongs to System.Collections and it existed in Net 1.0.
Collin Jasnoch wrote:
It should be understood and if it is not that means you lack the basic understanding of extensions which were added multiple frameworks ago. That is not my problem nor should it be.
Which is of course the attitude of every developer who does not consider code maintenance. One can as well claim that the updates that occurred in C# 5 requires that all APIs should be re-written to use asynchronous calls because after all they were added.
Collin Jasnoch wrote:
If the business chose/authorized the use of a framework it will be used
The the fact that it might be used in one place is in fact absolutely no justification for claiming that every one must be an expert in it. And further using that as a rationalization to suggest that every usage anywhere is thus justified. As a lone developer one can of course do what one wants but in team environments specialization provided benefits and teams that are even above a couple of people the members will not be experts in the entire application.
-
Collin Jasnoch wrote:
The
ForEach
extension forIList
which is within the "System.Linq" namespace is common knowledge for programmers using the .Net Framework 3.5 and up. Er it should be.And that namespace is more important than any of the other hundreds (thousands) because?
Collin Jasnoch wrote:
if it is not then you need to do some homework before touching a system built on that framework.
Sounds reasonable.
Collin Jasnoch wrote:
I chose the ForEach extension onto the
IEnumerable
because of this reasonI see absolutely no connection there. IEnumerable belongs to System.Collections and it existed in Net 1.0.
Collin Jasnoch wrote:
It should be understood and if it is not that means you lack the basic understanding of extensions which were added multiple frameworks ago. That is not my problem nor should it be.
Which is of course the attitude of every developer who does not consider code maintenance. One can as well claim that the updates that occurred in C# 5 requires that all APIs should be re-written to use asynchronous calls because after all they were added.
Collin Jasnoch wrote:
If the business chose/authorized the use of a framework it will be used
The the fact that it might be used in one place is in fact absolutely no justification for claiming that every one must be an expert in it. And further using that as a rationalization to suggest that every usage anywhere is thus justified. As a lone developer one can of course do what one wants but in team environments specialization provided benefits and teams that are even above a couple of people the members will not be experts in the entire application.
jschell wrote:
And that namespace is more important than any of the other hundreds (thousands) because?
Its not that it is more important, but it is clearly referenced, documented, and used. If a developer has a problem with a specific System namespace they may be in the wrong dev group.
jschell wrote:
I see absolutely no connection there. IEnumerable belongs to System.Collections and it existed in Net 1.0.
Really? So you do not understand when someone in plain English says "I have a collection and FOR EACH item in it..."
jschell wrote:
Which is of course the attitude of every developer who does not consider code maintenance.
One can as well claim that the updates that occurred in C# 5 requires that all APIs should be re-written to use asynchronous calls because after all they were added.Wrong. We can however state that the project/system is targeting framework XYZ (does not even need to be .Net). If the resource assigned to that system is not familiar with THE KEY FEATURES OF THAT FRAMEWORK vs other then they are the wrong resource or need to do some research.
jschell wrote:
The the fact that it might be used in one place is in fact absolutely no justification for claiming that every one must be an expert in it. And further using that as a rationalization to suggest that every usage anywhere is thus justified.
Sure, they do not need to be an expert but they need to understand it. Not only that but taking recommendations of what is "Bad" or "satan's" work from them is silly. I would never take recommendations from an Objective C programmer on a windows based system or vise versa. No your tools that are on your bench. Don't criticize the ones you are not familiar with.
jschell wrote:
As a lone developer one can of course do what one wants but in team environments specialization provided benefits and teams that are even above a couple of people the members will not be experts in the entire application.
I would argue that a lone team member actually can not do what he wants for when they leave the inner workings of the system are a then a mystery. A team however has someone left to always do train in new recruits. With that I go back to my original point. KISS. And hon
-
Sometimes I yearn for a return to .NET 2.0. The C# that came with it was a great language and now that generics were included it was essentially complete in my mind. Since then, they've been adding all sorts of dubious things to the language LINQ being the most notable but now we also have the async/await business which really is anything but the simple solution to asynchronous programming they tell us it is. Extensions methods, everyone's favourite encapsulation anti-pattern debuted with LINQ in order to make it work and some people (me) viewed them with suspicious eyes at the time but didn't really know how bad things could get. Having recently worked on a system where they have been abused to the fullest I can tell you. You start off with pretty hollow objects with very little in the way of methods, just enough to get at the data. Then, you put all your logic in extension methods, preferably in different assemblies. A sort of warped onion architecture. Now, any normal developer who goes looking for a type's methods won't find them in the type or even that assembly. A missing reference will make them disappear completely. Also, with careful planning, you can make it exceedingly hard to move that logic back where it belongs because doing so will cause all kinds of circular dependency issues. Immutable code! Shocking stuff, but if you really hate the world, don't forget the Action<> and Func<> delegates. These are useful because you can avoid passing meaningful data to methods. Instead just pass delegates everywhere (a functional programming approach I'm told). This makes it practically impossible for anyone to work out the execution flow by examining the code. Combine the two and you have one thoroughly malevolent system. People bang on about patterns all the time in software development, but if you ask me (I'm aware you didn't) the way to build a good system is to always, always, always keep everything as simple as you can make it.
Regards, Rob Philpott.
Rob Philpott wrote:
Extensions methods, everyone's favourite encapsulation anti-pattern debuted with LINQ in order to make it work (...)
Well, it did make it work, didn't it? Prior to that, you weren't able to provide any common functionality to an interface, without actually forcing all your subclasses to derive from a single common class. Since C# doesn't support multiple inheritance, this was the natural way to do it. And the fact that these are actually static methods that don't know anything about the concrete implementation is exactly what ensures that they will work with any implementation.
Rob Philpott wrote:
didn't really know how bad things could get
You should visit The Daily WTF [^] in that case. You will quickly learn that any programming construct can be abused beyond imagination.
Rob Philpott wrote:
Shocking stuff, but if you really hate the world, don't forget the Action<> and Func<> delegates. These are useful because you can avoid passing meaningful data to methods. Instead just pass delegates everywhere (a functional programming approach I'm told). This makes it practically impossible for anyone to work out the execution flow by examining the code. Combine the two and you have one thoroughly malevolent system.
Well, that's one of the main prerequisites for loose coupling, and you cannot accomplish it without going functional (or OOP, which basically boils down to functional programming). If you want to be able to test individual parts of your system, make your program easily extensible, and follow other points of the SOLID OOP principle, then I'm afraid you have to go past plain ol' procedural programming.
-
What, you don't like this code?
// Menu copy handler. If a control has focus and its an edit box, copy its text to the clipboard,
// otherwise if there's an active notecard instance, tell the notecard's view to do the copy to the clipboard.
protected void Copy(object sender, EventArgs args)
{
Program.GetFocusedControl().IfNotNull(ctrl =>
{
ctrl.Is(tb => tb.Copy());
}).Else(() => ActiveDocumentController.IfNotNull(notecard => notecard.NotecardView.Copy()));
};P Marc
Latest Article: C# and Ruby Classes: A Deep Dive
My BlogEww. I mean dude, c'mon. At least format that obscenity decently.
Software Zen:
delete this;
-
Eww. I mean dude, c'mon. At least format that obscenity decently.
Software Zen:
delete this;
Gary R. Wheeler wrote:
At least format that obscenity decently.
:) That's how it IS formatted in my code! Marc
Testers Wanted!
Latest Article: User Authentication on Ruby on Rails - the definitive how to
My Blog -
Gary R. Wheeler wrote:
At least format that obscenity decently.
:) That's how it IS formatted in my code! Marc
Testers Wanted!
Latest Article: User Authentication on Ruby on Rails - the definitive how to
My Blog// Menu copy handler. If a control has focus and its an edit box, copy its text to the clipboard,
// otherwise if there's an active notecard instance, tell the notecard's view to do the copy to the clipboard.
protected void Copy(object sender, EventArgs args)
{
Program.GetFocusedControl().IfNotNull(ctrl =>
{
ctrl.Is(tb => tb.Copy());
}).Else(
() => ActiveDocumentController.IfNotNull(notecard =>
notecard.NotecardView.Copy()));
}Everything I tried only made it worse...
Software Zen:
delete this;
-
// Menu copy handler. If a control has focus and its an edit box, copy its text to the clipboard,
// otherwise if there's an active notecard instance, tell the notecard's view to do the copy to the clipboard.
protected void Copy(object sender, EventArgs args)
{
Program.GetFocusedControl().IfNotNull(ctrl =>
{
ctrl.Is(tb => tb.Copy());
}).Else(
() => ActiveDocumentController.IfNotNull(notecard =>
notecard.NotecardView.Copy()));
}Everything I tried only made it worse...
Software Zen:
delete this;
Gary R. Wheeler wrote:
Everything I tried only made it worse...
Exactly. :) It's something I'm playing with as a syntax style, performance is probably terrible, but I wouldn't write code like this in algorithms that need to be performant. I like the terseness, though I think most other programmers would rip this stuff out and rewrite with traditional "if-else" blocks. Certainly, that's what I would have done a few years ago if I'd encountered something like this. Marc
Testers Wanted!
Latest Article: User Authentication on Ruby on Rails - the definitive how to
My Blog -
Gary R. Wheeler wrote:
Everything I tried only made it worse...
Exactly. :) It's something I'm playing with as a syntax style, performance is probably terrible, but I wouldn't write code like this in algorithms that need to be performant. I like the terseness, though I think most other programmers would rip this stuff out and rewrite with traditional "if-else" blocks. Certainly, that's what I would have done a few years ago if I'd encountered something like this. Marc
Testers Wanted!
Latest Article: User Authentication on Ruby on Rails - the definitive how to
My BlogMarc Clifton wrote:
I think most other programmers would rip this stuff out and rewrite with traditional "if-else" blocks
I'll freely admit that's my first reaction, even if I would have to use temporary variables in order to make the logic clearer. I've used extension methods in a few cases, mostly to enhance a built-in class for a particular purpose. The best example was a
GetUInt32()
and similar methods I attached to WPFTextBox
controls in an application. This app has literally hundreds of text boxes (it's a test bench widget), and I didn't want to fool with setting up prim-and-proper data binding.Software Zen:
delete this;
-
Marc Clifton wrote:
I think most other programmers would rip this stuff out and rewrite with traditional "if-else" blocks
I'll freely admit that's my first reaction, even if I would have to use temporary variables in order to make the logic clearer. I've used extension methods in a few cases, mostly to enhance a built-in class for a particular purpose. The best example was a
GetUInt32()
and similar methods I attached to WPFTextBox
controls in an application. This app has literally hundreds of text boxes (it's a test bench widget), and I didn't want to fool with setting up prim-and-proper data binding.Software Zen:
delete this;
Gary R. Wheeler wrote:
I've used extension methods in a few cases, mostly to enhance a built-in class for a particular purpose.
That's what I have been typically doing as well. A good example in my case was writing an extension method to iterate through a tree collection, as the functionality was not built into the tree control itself. I also have a variety of extension methods on things like the String class, and the typical pattern is to change the code syntax from "Do(with)" for example,
RightOfChar("fubar", 'u');
to "with.Do()""fubar".RightOf('u')
which is more in line with the style of calling methods on objects. I think it makes the code immensely more readable when adhering more consistently to a particular syntactical pattern, in this case, the "with.Do()" form. Any time one has to pass in the object as a requirement for the operation is a clue that an extension method might be a useful implementation. Hmmm, I've actually never tried extension methods on interfaces. Does this work (I sort of think not, but now I'm curious.) My particular foray though into using extension methods as control blocks where a function is passed in and executed based on the condition, well, that is admittedly rather divergent from the normal usage of extension methods. :) MarcTesters Wanted!
Latest Article: User Authentication on Ruby on Rails - the definitive how to
My Blog -
Roger Alsing wrote:
Bad coders write bad code..
So presumably you are claiming that your usage is correct and understandable. And it is only others that have problems? And perhaps only those that are less intelligent than you would have any trouble understanding it? What classes have you taken to issue that your usage is correct? What standards do you use to insure that your usage is something that most average developers would have or should have learned?
A bit late to reply here but that was not what I was saying. I was merely saying that all features can be abused, there is nothing wrong with extension methods per se. but they can be abused, just like inheritance, generics, lambdas etc. I was also pointing out that your agrument against extension methods with "you cant see what they do" also applies to other methods too. so thats not really a valid argument IMO.