I would like to have your opinion as to the pros and cons of using delegates instead of virtual functions aud subclassing?
I think the delegate issue is a red herring: this is really about the strategy pattern versus the template pattern.
"Favor composition over inheritance" is excellent advice, so the strategy pattern is the better default technique (whether you use objects or delegates to do your dirty work), mainly because it provides superior decoupling.
I only use subclassing (the template pattern) when there's a suitable inheritance relationship (per the Liskov Substitution Principle), the algorithm I'm varying needs access to the protected methods of the base class and I want a high degree of cohesion.
It very muych depends whether you're aiming for the object oriented or functional style really.
Object oriented => inheritance and overriding of methods
Functional => passing delegates to method
Usually it's best to pick one or the other, but sometimes it doesn't hurt to mix. I generally try to stick to the OO approach, since that is the main heritage of C#.
However, in certain circumstances, passing lambda epxressions to functions removes a lot of the boilerplate code. Indeed, in the extreme case, the alternative to creating a method that takes a delegate/lambda expression could be overriding the base class a dozen or so times with minor changes. Saying this, if the behaviour you want to customise is fairly fixed, than subclassing is usually the better choice.
Vague question, so you get a vague answer:
Use virtual methods and subclassing to represent a model. Use delegates to implement a mechanism.
See my answer to
When to use callbacks instead of events in c#?
for additional thoughts in this vein.
Here is my take.
Its not object oriented programming anymore. It's the old way of doing things.
Hm. That's all I have.
Related
Do extension methods follow the object-oriented paradigm in C#?
Is it a good practice to use extension methods?
In the software development lifecycle how should we consider this question in the design phase?
Eric Lippert has blogged about this and I suspect I can't do much better than to quote him:
So, yes, the oft-heard criticism that
"extension methods are not
object-oriented" is entirely correct,
but also rather irrelevant. Extension
methods certainly are not
object-oriented. They put the code
that manipulates the data far away
from the code that declares the data,
they cannot break encapsulation and
talk to the private state of the
objects they appear to be methods on,
they do not play well with
inheritance, and so on. They're
procedural programming in a convenient
object-oriented dress.
They're also incredibly convenient and
make LINQ possible, which is why we
added them. The fact that they do not
conform to some philosophical ideal of
what makes an object-oriented language
was not really much of a factor in
that decision.
I would add, however, that they're useful beyond just LINQ - for the same reason that they're useful in LINQ. It's really nice to be able to express algorithms which work on arbitrary implementations of a particular interface (such as IEnumerable<T> in LINQ to Obhects). Such algorithms typically don't have any context beyond the interfaces you're working on, so they're often naturally static.
If you accept that you've got some static utility method, which syntax would you rather use?
// Traditional
CollectionUtils.Sort(collection);
// Extension methods
collection.Sort();
The latter is simply more readable in my opinion. It concisely expresses what you want to do. It doesn't make it clear how you want to do it, but that's less important for most of the time - and more important when you're debugging that particular line, of course.
Extension methods are not an object oriented language feature. (compared to: classes, inheritance, polymorphism etc).
Like every language feature, it should be used where it is appropriate and for what it is designed for. There are already dozens of questions about when and how to use Extension methods.
What are the best practices for using Extension Methods in .Net?
Possible overuses of Extension Methods
Do Extension Methods Hide Dependencies?
There are two parts to it.
Is it OO when we use it
No; it makes you feel that you are calling method on the particular type
Is it OO based on how it is compiled/built
Yes; Compiled code has a static method using the object on which extension method was invoked
Extension methods are just a language feature. They work on object instances and are very nice tool.
Consider them as a different way to extend class functionality. You can add new functionality to a class:
By adding a partial class declaration. The class then instantly gets a bunch of new methods and properties.
By including a namespace with your extension methods holder class. The class then gets a bunch of new methods again.
Rather an organizational / language feature. Does not break object-oriented concept in any way. Just as header/source file division in C/C++ has nothing to do with object-orientation, just a language/framework feature.
It depends. Extension methods are just a tool. They can be very useful when used appropriately. But if you use them too much, it can obscure your code.
Extension Methods are just static methods that work with a specific Class or Class Hierarchy. Python is OO but has modules, Ruby has mixins. I see it more as a language feature. I am pretty sure its still OO friendly
I would like to know if C# extension method is based on any existing design pattern.
A design pattern is simply a well known paradigm, i.e. "when you want to achieve X, do Y". A well known paradigm in object-oriented languages such as C# is "when you want to act on the state of an object, call a method on an instance of it".
However, before extension methods were created, you could not call your own method on an instance of an object that you could not add an implementation to (e.g. interfaces because they cannot have implementations, or library classes because they are already compiled). Extension methods fill this gap by allowing you to make methods that appear to be callable on instances of objects, while being defined externally to the implementation of the object.
So yes, arguably extension methods are based on this very simple design pattern, of making methods that act on the state of an object appear to be callable from an instance of it.
The extension methods can be thought as a replacement of the Visitor Pattern. It is also proposed that they can be used as Adapters.
In general languages evolve to make the need of design patterns less necessary. There is a quote for example that Lisp doesn't need design patterns, because everything is built in the language. So the right question will be, what design patterns do extension methods replace?
No. It's just a language feature.
They are not based on an existing design pattern. When this 'feature' was first introduced in Delphi, under the name 'class helpers', Borland even warned users away from them. They were considered a bit of a hack, but now the dust has settled they have found a place of their own.
Like everything else, use when appropriate.
The closest canonical design patterns is probably the Decorator pattern.
No, they are not, because they are only syntactic sugar.
No, but extension methods are excellent for implementing certain GoF design patterns (e.g., Prototype).
Of course you can use C# extension methods if you want to implement certain design patterns. For example simulate mixins in C#.
I wouldn't label Extension Methods as any of the common design patterns, but it can be used to implement patterns like, Decorator and Adapter etc..
The best matching design pattern to extension method is Facade pattern.
My Reason: We usually use extension methods not to introduce a new functionality beyond the target class responsibility, but simplifying using existing target class usage.
Because simplifying the target class usage is the Facade pattern concern, extension methods can alternatively be implemented using the Facade pattern.
There are some problems in extending and unit testing extension methods. So I think implementing Facade pattern is a better approach against using extension methods.
However it is possible to implement some extension methods that wrap the facade interface in order to provide a coding facility for client codes.
I have used OO programming languages and techniques years ago (primarily on C++) but in the intervening time haven't done much with OO.
I'm starting to make a small utility in C#. I could simply program it all without using good OO practice, but it would be a good refresher for me to apply OO techniques.
Like database normalization levels, I'm looking for a checklist that will remind me of the various rules of thumb for a 'good' object oriented program - a concise yes/no list that I can read through occasionally during design and implementation to prevent me from thinking and working procedurally. Would be even more useful if it contained the proper OO terms and concepts so that any check item is easily searchable for further information.
What should be on a checklist that would help someone develop good OO software?
Conversely, what 'tests' could be applied that would show software is not OO?
Objects do things. (Most important point in the whole of OOP!) Don't think about them as "data holders" - send them a message to do something. What verbs should my class have? The "Responsibility-Driven Design" school of thinking is brilliant for this. (See Object Design: Roles, Responsibilities, and Collaborations, Rebecca Wirfs-Brock and Alan McKean, Addison-Wesley 2003, ISBN 0201379430.)
For each thing the system must do, come up with a bunch of concrete scenarios describing how the objects talk to each other to get the job done. This means thinking in terms of interaction diagrams and acting out the method calls. - Don't start with a class diagram - that's SQL-thinking not OO-thinking.
Learn Test-Driven Development. Nobody gets their object model right up front but if you do TDD you're putting in the groundwork to make sure your object model does what it needs to and making it safe to refactor when things change later.
Only build for the requirements you have now - don't obsess about "re-use" or stuff that will be "useful later". If you only build what you need right now, you're keeping the design space of things you could do later much more open.
Forget about inheritance when you're modelling objects. It's just one way of implementing common code. When you're modelling objects just pretend you're looking at each object through an interface that describes what it can be asked to do.
If a method takes loads of parameters or if you need to repeatedly call a bunch of objects to get lots of data, the method might be in the wrong class. The best place for a method is right next to most of the fields it uses in the same class (or superclass ...)
Read a Design Patterns book for your language. If it's C#, try "Design Patterns in C#" by Steve Metsker. This will teach you a series of tricks you can use to divide work up between objects.
Don't test an object to see what type it is and then take action based on that type - that's a code smell that the object should probably be doing the work. It's a hint that you should call the object and ask it to do the work. (If only some kinds of objects do the work, you can simply have "do nothing" implementations in some objects... That's legitimate OOP.)
Putting the methods and data in the right classes makes OO code run faster (and gives virtual machines a chance to optimise better) - it's not just aesthetic or theoretical. The Sharble and Cohen study points this out - see http://portal.acm.org/citation.cfm?doid=159420.155839 (See the graph of metrics on "number of instructions executed per scenario")
Sounds like you want some basic yes/no questions to ask yourself along your way. Everyone has given some great "do this" and "think like that" lists, so here is my crack at some simple yes/no's.
Can I answer yes to all of these?
Do my classes represent the nouns I am concerned with?
Do my classes provide methods for actions/verbs that it can perform?
Can I answer no to all of these?
Do I have global state data that could either be put into a singleton or stored in class implementations that work with it?
Can I remove any public methods on a class and add them to an interface or make them private/protected to better encapsulate the behavior?
Should I use an interface to separate a behavior away from other interfaces or the implementing class?
Do I have code that is repeated between related classes that I can move into a base class for better code reuse and abstraction?
Am I testing for the type of something to decide what action to do? If so can this behavior be included on the base type or interface that the code in question is using to allow more effect use of the abstraction or should the code in question be refactored to use a better base class or interface?
Am I repeatedly checking some context data to decided what type to instantiate? If so can this be abstracted out into a factory design pattern for better abstraction of logic and code reuse?
Is a class very large with multiple focuses of functionality? If so can I divide it up into multiple classes, each with their own single purpose?
Do I have unrelated classes inheriting from the same base class? If so can I divide the base class into better abstractions or can I use composition to gain access to functionality?
Has my inheritance hierarchy become fearfully deep? If so can I flatten it or separate things via interfaces or splitting functionality?
I have worried way too much about my inheritance hierarchy?
When I explain the design to a rubber ducky do I feel stupid about the design or stupid about talking to a duck?
Just some quick ones off the top of my head. I hope it helps, OOP can get pretty crazy. I didn't include any yes/no's for more advanced stuff that's usually a concern with larger apps, like dependency injection or if you should split something out into different service/logic layers/assemblies....of course I hope you at least separate your UI from your logic.
Gathered from various books, famous C# programmers, and general advice (not much if any of this is mine; It is in the sense that these are various questions i ask myself during development, but that's it):
Structs or Classes? Is the item you're creating a value of it's own, make it a struct. If it's an "object" with attributes and sub-values, methods, and possibly state then make it an object.
Sealed Classes: If you're going to be creating a class and you don't explicitly need to be able to inherit from it make it sealed. (I do it for the supposed performance gain)
Don't Repeat Yourself: if you find yourself copy-past(a/e)ing code around then you should probably (but not always) rethink your design to minimize code duplication.
If you don't need to provide a base implementation for a given abstract class turn it into an interface.
The specialization principle: Each object you have should only do one thing. This helps avoid the "God-object".
Use properties for public access: This has been debated over and over again, but it's really the best thing to do. Properties allow you to do things you normally can't with fields, and it also allows you more control over how the object is gotten and set.
Singletons: another controversial topic, and here's the idea: only use them when you Absolutely Need To. Most of the time a bunch of static methods can serve the purpose of a singleton. (Though if you absolutely need a singleton pattern use Jon Skeet's excellent one)
Loose coupling: Make sure that your classes depend on each other as little as possible; make sure that it's easy for your library users to swap out parts of your library with others (or custom built portions). This includes using interfaces where necessary, Encapsulation (others have mentioned it), and most of the rest of the principles in this answer.
Design with simplicity in mind: Unlike cake frosting, it's easier to design something simple now and add later than it is to design complex now and remove later.
I might chuck some or all of this out the door if i'm:
Writing a personal project
really in a hurry to get something done (but i'll come back to it later.... sometime..... ;) )
These principles help guide my everyday coding and have improved my coding quality vastly in some areas! hope that helps!
Steve McConnell's Code Complete 2 contains a lot of ready to use checklists for good software construction.
Robert C. Martin's Agile Principles, Patterns, and Practices in C# contains a lot of principles for good OO desgin.
Both will give you a solid foundation to start with.
Data belongs with the code that operates on it (i.e. into the same class). This improves maintainability because many fields and methods can be private (encapsulation) and are thus to some degree removed from consideration when looking at the interaction between components.
Use polymorphism instead of conditions - whenever you have to do different things based on what class an object is, try to put that behaviour into a method that different classes implement differently so that all you have to do is call that method
Use inheritance sparingly, prefer composition - Inheritance is a distinctive feature of OO programming and often seen as the "essence" of OOP. It is in fact gravely overused and should be classified as the least important feature
Have I clearly defined the
requirements? Formal requirements documentation may not be necessary, but you should have a clear vision before you begin coding. Mind-mapping tools and prototypes or design sketches may be good alternatives if you don't need formal documentation. Work with end-users and stakeholders as early as possible in the software process, to make sure you are implementing what they need.
Am I reinventing the wheel? If you are coding to solve a common problem, look for a robust library that already solves this problem. If you think you might already have solved the problem elsewhere in your code (or a co-worker might have), look first for an existing solution.
Does my object have a clear, single purpose? Following the principle of Encapsulation, an object should have behavior together with the data that it operates on. An object should only have one major responsibility.
Can I code to an interface? Design By Contract is a great way to enable unit testing, document detailed, class-level requirements, and encourage code reuse.
Can I put my code under test? Test-Driven Development (TDD) is not always easy; but unit tests are invaluable for refactoring, and verifying regression behavior after making changes. Goes hand-in-hand with Design By Contract.
Am I overdesigning? Don't try to code a reusable component. Don't try to anticipate future requirements. These things may seem counterintuitive, but they lead to better design. The first time you code something, just implement it as straightforwardly as possible, and make it work. The second time you use the same logic, copy and paste. Once you have two working sections of code with common logic, you can easily refactor without trying to anticipate future requirements.
Am I introducing redudant code? Don't Repeat Yourself (DRY) is the biggest driving principal of refactoring. Use copy-and-paste only as a first step to refactoring. Don't code the same thing in different places, it's a maintenance nightmare.
Is this a common design pattern, anti-pattern, or code smell? Be familiar with common solutions to OO design problems, and look for them as you code - but don't try to force a problem to fit a certain pattern. Watch out for code that falls into a common "bad practice" pattern.
Is my code too tightly coupled? Loose Coupling is a principle that tries to reduce the inter-dependencies between two or more classes. Some dependencies are necessary; but the more you are dependent on another class, the more you have to fix when that class changes. Don't let code in one class depend on the implementation details of another class - use an object only according to its contract.
Am I exposing too much information? Practice information hiding. If a method or field doesn't need to be public, make it private. Expose only the minimum API necessary for an object to fulfill its contract. Don't make implementation details accessible to client objects.
Am I coding defensively? Check for error conditions, and Fail Fast. Don't be afraid to use exceptions, and let them propagate. In the event your program reaches an unexpected state, it's much, much better to abort an operation, log a stack trace for you to work with, and avoid unpredictable behavior in your downstream code. Follow best practices for cleaning up resources, such as the using() {} statement.
Will I be able to read this code in six months? Good code is readable with minimal documentation. Put comments where necessary; but also write code that's intuitive, and use meaningful class, method, and variable names. Practice good coding style; if you're working on a team project, each member of the team should write code that looks the same.
Does it still work? Test early, test often. After introducing new functionality, go back and touch any existing behavior that might have been affected. Get other team members to peer review and test your code. Rerun unit tests after making changes, and keep them up to date.
One of the best sources would be Martin Fowler's "Refactoring" book which contains a list (and supporting detail) of object oriented code smells that you might want to consider refactoring.
I would also recommend the checklists in Robert Martin's "Clean Code".
SOLID
DRY
TDD
Composition over inheritance
Make sure you read up and understand the following
Encapsulation
(Making sure you only expose the minimal state and functionality to get the job done)
Polymorphism
(Ability for derived objects to behave like their parents)
The difference between and interface and an abstract class
(An abstract class allows
functionality and state to be shared
with it's descendants, an interface
is only the promise that the
functionality will be implemented)
I like this list, although it might be a little dense to be used as a checklist.
UML - Unified Modeling Language, for object modeling and defining the structure of and relationships between classes
http://en.wikipedia.org/wiki/Unified_Modeling_Language
Then of course the programming techniques for OO (most already mentioned)
Information Hiding
Abstraction
Interfaces
Encapsulation
Inheritance / Polymorphism
Some of the rules are language agnostic, some of the rules differ from language to language.
Here are a few rules and comments that contradict some other the previously posted rules:
OO has 4 principles:
Abstraction, Encapsulation, Polymorphism and Inheritence.
Read about them and keep them in mind.
Modelling - Your classes are supposed to model entities in the problem domain:
Divide the problem to sub-domains (packages/namespaces/assemblies)
then divide the entities in each sub-domain to classes.
Classes should contain methods that model what objects of that type do.
Use UML, think about the requirements, use-cases, then class diagrams, them sequences.
(applicable mainly for high-level design - main classes and processes.)
Design Patterns - good concept for any language, implementation differs between languages.
Struct vs. class - in C# this is a matter of passing data by value or by reference.
Interface vs. base-class, is a base-class, does an interface.
TDD - this is not OO, in fact, it can cause a lack of design and lead to a lot of rewriting. (Scrum for instance recommends against it, for XP it is a must).
C#'s Reflection in some ways overrides OO (for example reflection based serialization), but it necessary for advanced frameworks.
Make sure classes do not "know of" other classes unless they have to, dividing to multiple assemblies and being scarce with references helps.
AOP (Aspect Oriented Programming) enhances OOP, (see PostSharp for instance) in a way that is so revolutionary that you should at least look it up and watch their clip.
For C#, read MS guidelines (look up guidelines in VS's MSDN help's index),
they have a lot of useful guidelines and conventions there
Recommended books:
Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries
C# 3.0 in a Nutshell
I wonder what's the pros/cons of using delegate vs OOP when implementing strategy design pattern?
Which one do you recommend to use? or what kind of problem does delegate solve? and why should we use OOP if OOP is better?
Thanks!
-tep
Both techniques can be powerful and valuable - here are some of my opinions about when to use which.
Use an Interface/Implementation approach when the strategy:
maintains state
needs configuration
uses dependency injection
needs to be configured by an IoC container (think ConnectionProvider)
combines multiple responsibilities (think DataAdapter from ADO.NET)
is too complex or long as a single method
is likely to be subclassed to create new strategies
needs to return state information to the caller
needs to access internals of the object is applies to
Would require too many direct parameters
Otherwise, tend to use delegates based on Func<> or Action<>, especially if
There are likely to be a very large variety of strategies (think sort expressions)
The strategy is best expressed as as lambda
There's an existing method you want to leverage
In favour of delegates:
Delegates are easier to implement in a light-weight way using lambda expressions and dynamic methods
Delegates can be created from "normal" methods with the right signature
Delegates being multi-cast can be useful at times (though relatively rarely outside eventing)
In favour of interfaces:
An object can implement an interface and still do other things: a delegate is just a delegate
An interface can have multiple methods; a delegate just has the one
Could go either way:
With interfaces you end up with two names: the interface and the method. With delegates you just have the one. Often I find that single-method interfaces either repeat the same name twice (with variations) or the method name is very bland
Personally I'm a big fan of delegates for their flexibility, but it really depends on the situation.
In my opinion, if you use delegates then you're not actually implementing the Strategy pattern. You're actually implementing something more akin to the Observer pattern. The whole point of design patterns is that when you say "I've used the Strategy pattern here," everyone has a lot of context on what you've done. When you start saying things like "I've used the Strategy pattern except with my own personal modifications," then things get dicey.
But, if I understand what you're trying to say, one of the nice things about the Strategy pattern that isn't so clear with delegates is you can have a hierarchy of objects that implement a strategy.
Let's say that I'm testing some piece of software. I want to test it using the mouse and using the keyboard. So I'll implement a Strategy pattern to plug in the interface method to use for each test case ... so I can write the test case once and run it completely using the MouseStrategy and KeyboardStrategy. From there I can implement specializations such as MouseExceptForDialogsStrategy, a specialization of MouseStrategy. This sort of hierarchy, how to extend it and override it is easily understood by anyone familiar with OOP concepts ... whereas how to achieve and extend the same with delegates is much more complicated and very much more obscure.
As with many things ... it is not a question of "can you do it?", but "should you do it?".
I like to use an interface to abstract my strategy. My concrete implementations then have a visible file for each strategy. When working with a Class instead of a method it gives you more flexibility. I can use Rhino mocks to mock out the strategy to test around it. I can also easy use DI frameworks such as Ninject to bind the strategy application wide very easily. I use Delegates to extract the implementation mostly in WinForm Dialogs.
According to this Pluralsight blog post:
The primary difference between Delegates and Interfaces is that while delegates reduce the code base and increase readability of code, you have to be careful on how you use them otherwise you might end up sacrificing testability. Coding to interfaces is usually more reliable, even if it requires more code
I've been looking at strategy pattern implementation examples and it seems to me like they are very similar to c# delegates. The only difference I see is that strategy pattern implementations don't need to explicitly declare a delegate.
But other than that, they both seem to point to functions that need a specific signature and they can both be used to determine what to execute at run time.
Is there a more obvious difference that I am missing?
I guess a related question would be, IF they are similar, what's the advantage of using one over the other?
Put simply, you can use delegates to implement strategy pattern.
Strategy pattern is a pattern. Delegates are a language feature. You use the language feature to implement the pattern. They reside in two separate categories of concepts altogether, but are related in their interaction with each other.
In other words, strategy pattern is the blueprint, the C# delegates are the bricks. You can't build the (strategy pattern) house without either. (You could build it with other kinds of bricks also, but nothing in the language feature of delegates inherently describes strategy pattern).
Design Patterns are language agnostic, high-level solutions to commonly-encountered problems.
Delegates can be used in a platform-specific implementation of the strategy pattern for .NET, but aren't the only way of implementing such a solution.
An alternative solution is to define an interface like:
public interface IStrategy
{
void DoStuff(...)
}
Strategies would then be represented by classes implementing this interface, rather than by a delegate.
Delegates may be an okay implementation if you expect your strategies to be very simple. For anything reasonably complex, implementing strategies as interfaces gives you a lot more options when it comes to keeping track of state, organizing things into multiple methods, sharing code between implementations, etc.
How else would you implement the strategy pattern in C#?
Patterns are a matter of architecture. Delegates are a matter of implementation.
In C#, a strategy pattern will nearly always be implemented using a delegate.
The strategy pattern is a design pattern that allows you to choose distinct functions at execution time while a delegate is a language construct that allows you to create a reference to a function and use it as a variable.
The strategy pattern is better implemented with polymorphism rather than delegates as polymorphic dispatch tends to be more elegant.
Delegates can be seen similar to a functional interface used in Java - Essentially an interface with just one method.
Starting Java8, you can actually provide implementations to functional interfaces, in a much more anonymous/in-line way.
For a behaviour that can be covered by a single method, doing a strategy implementation is kind of an overkill, and too verbose.
They essentially solve the same purpose of "inserting swappable behaviours in a class"