Inversion of Control (IoC / Dependency Injection) for Dummies [duplicate] - c#

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
What is Inversion of Control?
Okay, I'm new to this site and I've seen that people is really willing to help, so imma take advantage of that and just ask another question if you don't mind.
So, I've readed a lot, I swear, BUT, I just can't seem to figure it out. WHAT in the world is Inversion of Control (IoC or Dependency Injection)? Why are ASP.NET MVC + Repository Pattern projects using it so much? And lastly, what they mean by "containers" and when they say "Inject my Controllers"?
I know it might be an old topic (or even a dumb question) but I just can't seem to get any for-dummies answers.

Think of Dependency Injection/Inversion of Control as little more than a big object factory, a declarative, configuration-driven virtual constructor. Instead of littering your code with calls to "new" that hardwire the concrete type that your client class uses, you're now going to have that virtual constructor instantiate objects for you.
What's the advantage that all that complexity is buying you?
Object creation is now a declarative thing. If you happen to base your design on appropriate interfaces, you can ask the the object factory to create a proxy that implements the same interface when it's convenient. All kinds of good things are now possible: aspect-oriented programming, transparent remoting, declarative transactions, etc.

Simple answer: It lets you hand in the "things" that any given object will use to do its work.
Contrived Example: Say the object wants to get the time for some purpose, you hand it a "ITimeService" and it calls "GetTime" on that.
The purpose of this is to "de-couple" the class from having hard relationships to things you may not wish it, and to aid testing.
In my humble opinion some people go a little overboard, but the testing argument is a valid one, and certainly it's an approach that is useful to adopt at times.
More involved answer: Martin Fowler on Inversion of Control.

Related

Using Ninject with ServiceLocater pattern - good or bad [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I'm about to get used to Ninject. I understand the principles of Dependency Injection and I know how to use Ninject. But I'm a little confused right now. The opinions drift apart when it comes to the Service Locator pattern.
My application is built upon a strictly modular basis. I try to use constructor injection as much as I can and this works pretty well, though it's a little bit messy (in my opinion).
Now when an extension (external code) wants to benefit from this system, wouldn't it be required to have access to the kernel? I mean right now I have one static class which gives access to all subsystems of my application. An alternative would be having access to the kernel (Service Locator pattern) and grabbing the subsystem dependencies from this one.
Here I can easily avoid giving access to the kernel or to be more explicit, not allowing dependencies to the kernel.
But if an extension now wants to use any components (interfaces) of my application, from any subsystem, it would be required to have access to the kernel in order to resolve them because Ninject does not automatically resolve as long as you're not using "kernel.Get()", right?
Peww, it's really difficult explaining this in an understandable way. I hope you guys get what I'm aiming for.
Why is it so "bad" having a dependency to the kernel or a wrapper of it? I mean, you can't avoid all dependencies. For example I still have the one to my "Core" class which gives access to all subsystems.
What if an extension wants to register it's own module for further usage?
I can't find any good answer for why this should be a bad approach, but I read it quite often. Moreover it is stated that Ninject does NOT use this approach unlike Unity or similiar frameworks.
Thanks :)
There are religious wars about this...
The first thing that people say when you mention a Service Locator is: "but what if I want to change my container?". This argument is almost always invalid given that a "proper" Service Locator could be abstract enough to allow you to switch the underlying container.
That said, use of a Service Locator has in my experience, made the code difficult to work with. Your Service Locator must be passed around everywhere, and then your code is tightly coupled to the very existence of a Service Locator.
When you use a Service Locator, you have two main options to maintain modules in a "decoupled" (loosely used here..) way.
Option 1:
Pass your locator into everything that requires it. Essentially this means your code becomes lots and lots of this sort of code:
var locator = _locator;
var customerService = locator.Get<ICustomerService>();
var orders = customerService.GetOrders(locator, customerId); // locator again
// .. further down..
var repo = locator.Get<ICustomerRepository>();
var orderRepo = locator.Get<IOrderRepository>();
// ...etc...
Option 2:
Smash all of your code into a single assembly and provide a public static Service Locator somewhere. This is even worse.. and ends up being the same as above (just with direct calls to the Service Locator).
Ninject is lucky (by lucky I mean - has a great maintainer/extender in Remo) in that it has a heap of extensions that allow you to fully utilise Inversion of Control in almost all parts of your system, eliminating the sort of code I showed above.
This is a bit against SO's policy but to extend on Simon`s answer i'll direct you to Mark Seeman's excellent blog post: http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/
Some of the comments to the blog post are very interesting, too.
Now to address your problem with ninject and extensions - which i assume are unknown to you/the composition root at the time when you write them - i would like to point out the NinjectModules. Ninject already features such an extensibility mechanism which is heavily used with/by all ninject.extension.XYZ dlls.
What you'll do is implement some FooExtensionModule : NinjectModule classes in your extensions. The Modules contain the Bind methods. Now you'll tell ninject to load all Modules from some .dll's. That's it.
It's explained in far more greater detail here: https://github.com/ninject/ninject/wiki/Modules-and-the-Kernel
Drawbacks:
Extensions depend on Ninject
you may need to recompile your extensions when you "update ninject"
as the software grows, it will make it more and more expensive to switch DI containers
When using Rebind issues may arise which are difficult to track down (well this is the case whether your using Modules or not.)
Especially when extension-developers don't know about other extensions, they might create identical or conflicting bindings (such as .Bind<string>().ToConst("Foo") and .Bind<string>().ToConst("Bar")). Again, this is also the case when you're not using Modules, but extensions add one more layer of complexity.
Advantage:
- simple and to the point, there's no extra layer of complication/abstraction which you'd need to abstract the container away.
I've used the NinjectModule approach in a not-so-small Application (15k unit/component tests) with a lot of success.
If all you need are simple bindings like .Bind<IFoo>().To<Foo>() without scopes and so on, you might also consider using a simpler system like putting attributes on classes, scanning for these, and creating the bindings in the composition root. This approach is way less powerful but because of that it is much more "portable" (adaptable to be used with other DI container), too.
Dependency Injection an late instantiation
the idea of composition root is, that (whenever possible) you create all objects (the entire object graph) in one go. For example, in the Main method you might have kernel.Get<IMainViewModel>().Show().
However, sometimes this is not feasible or appropriate. In such cases you will need to use factories. There's actually a bunch of answers to this regard on stackoverflow already.
There's three basic types:
To create an an instance of Foo which requires instances of Dependency1 and Dependency2 (ctor injected), create a class FooFactory which gets one instance of Dependency1 and Dependency2 ctor injected itself. The FooFactory.Create method will then do new Foo(this.dependency1, this.dependency2).
use ninject.extensions.Factory:
use Func<Foo> as a factory: you can have a Func<Foo> injected and then call it to crate an instance of Foo.
use interfaces and .ToFactory() binding (i recommend this approach. Cleaner code, better testability). For example: IFooFactory with method Foo Create(). Bind it like: Bind<IFooFactory>().ToFactory();
Extensions which replace Implementations
IMHO this is not one of the goals of dependency-injection containers. That doesn't mean it's impossible, but it just means you've got to figure it out yourself.
The simplest you could to with ninject would be to use .Rebind<IFoo>().To<SomeExtensionsFoo>(). However, as stated before, that's a bit brittle. If the Bind and Rebind are executed in the wrong sequence, it fails. If there's multiple Rebinds, the last will win - but is it the correct one?
So let's take it one step further. Imagine:
`.Bind<IFoo>().To<SomeExtensionsFoo>().WhenExtensionEnabled<SomeExtension>();`
you can devise your own custom WhenExtensionEnabled<TExtension>() extension method which extends the When(Func<bool> condition) syntax method.
You'll have to devise a way to detect whether an extension is enabled or not.

Is there a better way than using static classes or singletons for MVVM?

I've found that in a lot of cases, it seems (at least superficially) to make sense to use Singletons or Static classes for models in my WPF-MVVM applications. Mostly, this is because most of my models need to be accessed throughout the application. Making my models static makes for a simple way of satisfying this requirement.
And yet, I'm conflicted because everyone on the planet seems to hate singletons. So I'm wondering I there isn't a better way, or if I'm doing something obviously wrong?
There are a couple of issues with Singletons. I'll outline them below, and then propose some alternative solutions. I am not a "Never use a singleton, or you're a crap coder" kind of guy as I believe they do have their uses. But those uses are rare.
Thread safety. If you have a global-static Singleton, then it has to be thread-safe because anything can access it at any time. This is additional overhead.
Unit Testing is more difficult with Singletons.
It's a cheap replacement for global variables (I mean, that's what a singleton is at the end of the day, although it may have methods and other fancy things).
See, it's not that Singleton's are "horrid abominations" per-se, but that it's the first design pattern many new programmers get to deal with and its' convenience obfuscates its' pitfalls (Just stick some gears on it and call it steam-punk).
In your case, you're referring to Models and these are always "instances" as they naturally reflect the data. Perhaps you are worried about the cost of obtaining these instances. Believe me, they should be negligible (down to data-access design, obviously).
So, alternatives? Pass the Model to the places that require it. This makes unit testing easier, and allows you to swap out the fundamentals of that model in a heart-beat. This also means you might want to have a look at interfaces - these denote a contract. You can then create concrete objects that implement these interfaces and voila - you're code is easily unit-testable, and modifiable.
In the singleton world, a single change to that singleton could fundamentally break everything in the code-base. Not a good thing.
I think the accepted solution to this problem is to use dependency injection. With dependency injection, you can define your models as regular, non-static classes and then have an inversion of control container "inject" an instance of your model when you want it.
There is a nice tutorial at wpftutorial.net that shows how to do dependency injection in WPF: http://wpftutorial.net/ReferenceArchitecture.html
The only static class I use is a MessageBroker because I need the same instance all through the application.
But even then it is very possible to use Unity (or another Dependency Injection/Container) to manage instances of classes that you only need one of.
This allows you to inject different versions when needed (e.g. during unit tests)
BTW: static is not the same as singleton. But I am not getting into that here. Just search stackoverflow for more fun questions on that :)

What strategies enable use of an IoC container in a library? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
Shorter version of the rest of the question: I've got a problem, and an IoC container is a tool. The problem sounds like something IoC might be able to solve, but I haven't read enough of the tool's instructions to know for sure. I'm curious if I picked the wrong tool or which chapter of the instruction manual I might be able to skip to for help.
I work on a library of Windows Forms controls. In the past year, I've stumbled into unit testing and become passionate about improving the quality of our automated tests. Testing controls is difficult, and there's not much information about it online. One of the nasty things is the separation of interaction logic from the UI glue that calls it leads to each control having several more dependencies than I would normally consider healthy for a class. Creating fakes for these elements when testing their integration with the control is quite tedious, and I'm looking into IoC for a solution.
There's one hurdle I'm not sure how to overcome. To set up the container, you need to have some bootstrapper code that runs before the rest of the application. In an application there is a very clear place for this stuff. In a library it's not so clear.
The first solution that comes to mind is creating a class that provides a static instance of the container and sets up the container in its type initializer. This would work for runtime, but in the test environment I'm not sure how well it would work. Tests are allowed to run in parallel and many tests will require different dependencies, so the static shared state will be a nightmare. This leads me to believe the container creation should be an instance method, but then I have a chicken and egg problem as a control would have to construct its container before it can create itself. The control's type initializer comes to mind, but my tests won't be able to modify this behavior. This led me to think of making the container itself a dependency of the control where user-visible constructors provide the runtime default implementation, but this leaves it up to my tests to set up their own containers. I haven't given this much thought, but it seems like this would be on the same level of effort as what I have now: tests that have to initialize 3-5 dependencies per test.
Normally I'd try a lot of things on my own to see what hurts. I'm under some harsh deadlines at the moment so I don't have much time to experiment as I write code; I only get brief moments to think about this and haven't put much to paper. I'm sure someone else has had a similar problem, so it'd be nice if I didn't have to reinvent the wheel.
Has anyone else attacked this problem? Are there some examples of strategies that will address these needs? Am I just a newbie and overcomplicating things due to my inexperience? If it's the latter, I'd love any resources you want to share for solving my ignorance.
Update:
I'd like to respond to Mark Seeman's answer, but it will require more characters than the comment field allows.
I'm already toying with presentation model patterns. The view in this case is the public control class and each has one or more controller classes. When some UI event is triggered on the control, the only logic it performs is deciding which controller methods need to be called.
The short expression of an exploration of this design is my controller classes are tightly coupled to their views. Based on the statement that DI containers work with loosely coupled code I'm reading "wrong tool for the job". I might be able to design a more loosely coupled architecture, at which point a DI container may be easier to use. But that's going to require some significant effort and it'd be an overhaul of shipped code; I'll have to experiment with new stuff before tiptoeing around the older stuff. That's a question for another day.
Why do I even want to inject strongly coupled types rather than using local defaults? Some of the seams are intended to be extensibility points for advanced users. I have to test various scenarios involving incorrect implementations and also verify I meet my contracts; mock objects are a great fit.
For the current design, Chris Ballard's suggestion of "poor man's DI" is what I've more or less been following and for my strongly coupled types it's just a lot of tedious setup. I had this vision that I'd be able to push all of that tedium into some DI container setup method, but the more I try to justify that approach the more convinced I become that I'm trying to hang pictures with a sledgehammer.
I'll wait 24 hours or so to see if discussion progresses further before accepting.
Dependency Injection (Inversion of Control) is a set of principles and patterns that you can use to compose loosely coupled code. It's a prerequisite that the code is loosely coupled. A DI Container isn't going to make your code loosely coupled.
You'll need to find a way to decouple your UI rendering from UI logic. There are lots of Presentation Patterns that describe how to do that: Model View Controller, Model View Presenter, Presentation Model, etc.
Once you have good decoupling, DI (and containers) can be used to compose collaborators.
Since the library should not have any dependency on the ioc framework itself we included spring.net ioc config xml-files with the standard configuration for that lib. That was modular in theory because every dll had its own sub config. All sub-configs were then assembled to become a part of the main confing.
But in reality this aproach was error prone and too interdependent: one lib config had to know about properties of others to avoid duplicates.
My conclusion: either use #Chris Ballard "poor man's dependency injection" or handle all dependencies in on big ugly tightly coupled config-module of the main app.
Depending on how complex your framework is, you may get away with handcoding constructor based dependency injection, with a parameterless default constructor (which uses the normal concrete implementation) but with a second constructor for injecting the dependency for unit test purposes, eg.
private IMyDependency dependency;
public MyClass(IMyDependency dependency)
{
this.dependency = dependency;
}
public MyClass() : this(new MyDefaultImplementation())
{
}

How Can I Learn when to build my own Interfaces [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
Interfaces: Why can’t I seem to grasp them?
How will I know when to create an interface?
I am using C# and I know what are the interfaces and how syntatically use them,etc.
but what I have not learned yet is that when I am tasked to write a project, create a component,... How should I learn better about interfaces so when I want to do something I be able to Think about using them in my design...or for example I want to learn about dependency injection or even using mocking objects for testing, these are all related to good understanding of interfaces and know when and how to use them ... Can you plase provide me some good advice, reading,... then can help me with that?
Use interfaces when you have several things that can perform a common set of actions. How they do those actions can be different, but when as far as using the classes they act the same.
A good real world example is like a network drive vs a regular hard drive. Either way you can perform basic file operations. How they're actually done is different, but most of the time when you want to do something on a drive you don't care if it's a network drive or a physical one. That's an interface.
In hardware, different keyboards are designed differently, they (could) have buttons in different locations, but none of that matters to the computer. The computer's view of a keyboard's interface is the same regardless of any aspects other than it sends key strokes.
What is the interface these things must have in common if they are going to be used in the same way?
If you can answer that then you are on your way to design and using the interface properly in real life scenarios.
The goal of interfaces is to reduce coupling between components of your application. By using interface, you are binding to a contract instead of an implementation. This means that you can change the implementation as you see fit, provided you follow the same contract.
For example, it is considered good practice to use IList<T> instead of List<T>, because IList<T> only states that you need something that acts like a list. This way, other implementations of lists can be substituted without affecting your code. (For example, NHibernate, an object mapping and data access library, uses this to allow lazy loading of collections.)
Excellent candidates for interfaces are classes that interact with external systems (File system, database, network, web services, etc...). If you directly use those systems in your code, you will have trouble testing and refactoring.
I personally find interfaces especially useful in dependency injection and testing scenarios. Since you already understand what interfaces are, you should be able to understand dependency injection. Reading on those concepts will help you recognize good candidates for interfaces.
It's really something that you learn to use with experience.
I've found understanding how interfaces are used in plugin architectures really helpful.
Lots of links out there, e.g. : http://www.codeproject.com/KB/cs/c__plugin_architecture.aspx
Try to imagine how you might write that sort of architecture without using interfaces - then you might fully appreciate what they bring to the table.
If using a a TDD-like workflow, interfaces are often used to define the requirements an object has of another object that it will eventually use. Using interfaces in this fashion allows them to be used to create 'seams' in your application where logic can be replaced/inserted/etc.
One way of thinking about interfaces in this fashion is to think of your objects as sending messages to one another, and that the interfaces are the definitions of the messages that can be sent.

What should be on a checklist that would help someone develop good OO software?

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

Categories

Resources