RE: Extension Methods - The devious evils lurking in your code
There are two very different use cases, extensions vs member functions. They are also two different ways of programming.
Also it is not as clear cut as you make out. In C# along with other OO languages there are actually no such things as member variables. They are actually just static methods with a hidden first param, the this pointer. There is also some vtable magic for virtual methods. Again all static.
So in reality member variables are just syntax sugar also :)
LINQ makes heavy use of extensions, but then it was influenced by Haskell and list comprehensions.
Over the years of using C# I have moved away from using it OO to a more functional approach, it is the way the language has been moving since C# 3.5.
Used correctly they allow higher code reuse. OO has seen its own fair share of abuse. Inheritance trees when they should not be used etc, that is its own crime :)
Say I have a few different unrelated classes that happen to carry similar data. If I give them an interface that has just that common data. Now I can create an extension to operate on that interface, no need to try and incorrectly munge them from a common base class or implement the same method in all. More like scala traits in that respect.
I use extensions on enums also. Say I have an enum for bank account types:
I might create the following
public static bool CanWithdrawMoney(this AccountTyoe accountType)
{
var canWithdraw = new[]{Deposit, Savings};
return canWithdraw.Contains(accountType);
}
Extensions are more for a types and functions style vs classes and members style. Both are equally valid.
Take a look through some of my posts, I expand on this a lot :)
While I agree there are good and bad uses of them, just like anything in programming. I think there should be careful consideration over whether or not extension methods should be used at all. There are cases where they are the best option but when used poorly they create future issues with code maintenance and testing.
Currently I see extension methods being over used in our code base.
Inheritance is extremely over used too, sometimes the way that inheritance trees get they can be a pain to maintain as well.
I have been moving to a more functional approach in some areas as well.
The biggest problem I see with extension methods though is they tend to spiral out of control when used incorrectly just as inheritance trees get too deep and themselves create too many dependencies.
It's also perfectly acceptable to me if people use extension methods but please try not to tie them to specific inheritance trees or specific implementations.
I'm also open to suggestions.
The particular problem I have is the extension methods we have are written in such a way that they have too many dependencies and become a pain to write unit tests for as there is no way to easily test things which have dependencies you can't isolate your test code from. For example we have extension methods that call extension methods in a very deep chain and it makes writing a unit test quite a pain.
@woz.software To be perfectly clear, our code base is not functional except in places where I use a lot of LINQ to solve problems in a more functional way but not purely functional. The main problem is each extension method developed can have some number of parameters and acts on a domain object from our datalayer and can call n number of methods doing the same in a really unit-test-unfriendly way and also the cyclomatic complexity of each method is far too high for my liking, I have been trying to break it into much smaller functions that do one thing and one thing only well but there's a lot going on in the smalltalk code that I've been porting to C# in each method and it's not very clear cut either.
Yep see where you are coming from. If you are full on OO code then that should be followed. agreed
For testing, the thing I have found when people get full on OO, that functions and dependencies grow to much and so to test something you need to build up complex test objects or driving mocking frameworks.
That is what pushed me away from OO, I like small self contained functions that I can test in a few lines, then plug them together.
I am currently porting old VB to C#, for my sins. Years back when I started this (Its that big) I tried to follow the logic in the VB. No I just try and extract what is really going on, then clean room it. Not follow the original design.
Get a lot cleaner code then
And yep, seen enough extension method abuse in my time lol
"That is what pushed me away from OO, I like small self contained functions that I can test in a few lines, then plug them together." <=== Totally my goal
That's the thing with dependencies, they tend to grow. We have monolithic 'functions' in the smalltalk side of things that are incredibly complex but they can be simplified quite a bit after hours of going down the rabbit hole of code.
Smalltalk bills itself as the original OO language but the smalltalk code I've looked at is way to big. There are smalltalk methods that easily get to be 50-100 lines or more and each method calls a similar sized chunk of code.
Personally I think a single method should be able to be seen and understood with no details hidden and with very few dependencies(classes or other structures) and should be at most 20 lines of code. I think if a single method is longer than that then you probably aren't breaking it into small enough pieces.
I had similar a while back. A 3500 line VB6 function that I got down to 300 lines of tiny functions :)
Btw I read your "Functional programming for the OO developer" series.
Good posts, got me to think more about a more functional approach to writing code.
Glad to hear it helped. You might find this a good talk. Found the other day, eye opening on how the parsers are put together. Great talk, funny guy and so well put across :)
YouTube - Write A Compiler in 24 hours