Adding Ninject to Legacy Project C# - c#

I have just inherited a legacy C# & VB.Net project which I will have to maintain and augment from now how.
There are no interfaces and obviously no Dependency Injection.
The first thing I am thinking of doing is creating interfaces and adding NInject, which would then make it possible to unit test the project eventually.
Is it a good idea or should I leave it alone ?
What are the best practices for implementing DI when it comes to legacy projects.
Thanks

I don't think there's a set best practice, other than use common sense - it's kind of a case by case scenario. A few important questions to ask yourself:
How much effort is going to be required to create interfaces for the current classes?
How much additional effort is going to be required to write proper
unit tests? Will these unit tests add more value than the time spent?
How long is this legacy system even going to be maintained? There's
nothing worse than doing a huge upgrade (requiring testing not only
by the development staff, but by the product user) to replace it in
18 months.
Also, how long has this legacy system been in place
without issue? There's no reason to invent work if it appears stable
and really has low maintenance.

Related

ASP.Net MVC Controller injection

I am looking for suggestions on good ways to design a new ASP.NET Mvc project. It is of medium size and is relatively simple in structure. I had initially used Spring.Net to wire my service objects into the correct constructors but now management has told me that Spring.Net or any other IOC container is not to be use in our environment.
I am having a bit of trouble figuring out a good way to set this up without DI. I would like to be able to assign service implementations to controllers in a way that allows for a low amount of coupling between controllers and services and to limit, as much as possible, the dependably of controllers on individual service implementations. I guess my question boils down to that fact that I am unsure of where I should manually wire up my application in the MVC model.
Any suggestions?
Since you are using ASP.NET MVC 3 you could write a custom dependency resolver. You will of course still design your controllers taking interfaces in their constructors in order to weaken the coupling between the layers. And then in the custom dependency resolver, in order to satisfy the ridiculous requirement that was imposed to you, you will have to manually say that when you have an ISomeService you return an instance of SomeServiceImpl. You know, the kind of things that object containers and DI frameworks already do for you. So you will basically have to reinvent some wheels. By the way Ayende blogged about how you could build a custom IoC container in 15 lines of code but of course that's not a reason that you should ever do anything like this.
People imposing such requirements should face a trial and be sentenced to never ever have to approach an application design. Imposing such requirement illustrates some total lack of knowledge about good practices in designing applications. Those people should be advised before they bring further damage to the company.
So simply explain those people that by reinventing wheels there are 2 mistakes:
you will waste a lot of time for something that was already done by someone else
you will make errors as you will not take into considerations all the edge cases that were taken into account by someone else designing a reusable DI framework.
At the end of the day you will ship your application late on schedule (as you would have wasted time to write plumbing code) and even worse you will ship an application that will contain potential bugs.
Conclusion: expensive and buggy product. Your management must have really has lost its mind :-)
Conclusion2: use an existing DI framework. Management won't even notice as they don't seem to understand the technical aspects of an application by imposing such requirements.
First of all, I would question why management has mandated that you can't use a pattern and tools that would allow you to achieve loose coupling and dependency injection. Is this something that can be discussed and reasoned about?
With an IoC container, it is trivial to implement an IControllerFactory that resolves controllers from the container and injects the necessary services.
In MVC 3, there is IDependencyResolver which you could use to achieve slightly looser coupling (via a Service Locator pattern/anti-pattern) than instantiating services directly inside controllers; this interface was designed to be used with an IoC container though really and would be a poorer substitute on its own.
Does your boss have pointy hair? http://www.dilbert.com/
You could save yourself some time by using http://unitymvc3.codeplex.com/ rather than writing your own custom dependency resolver. It's downloadable via Nuget http://nuget.org/. If you use an IOC container such as this, and use constructor injection, you will find your unit tests are much easier to write. That's assuming your manager believes in unit testing ;-) Good luck!
management has told me that Spring.Net or any other IOC container is
not to be use in our environment.
Management is telling you that you are not allowed to write loose coupled, testable and higly maintainable applications, that’s what they are telling you. That’s an odd restriction.
Dependency injection is an advanced technology that many developers don't understand. However, management will never understand it, and it is not their job to understand it. They may dictate the type of technology (.NET vs. Java for instance), because this impacts the kinds of personnel they need to hire, but when they start dictating on low level implementation details that prevent you from writing descent software, your company is heading for disaster.
Leave that company now you can!
Your other option is using the source code of the Simple Injector. The code base is small enough (about 500 lines, just use the SimpleInjector.NET project) to be able to copy it to a local project (and the license permits it). This way it’s your own local DI container, but fully tested :-)
Good luck.
You need a new home. There are plenty of organizations looking for talented engineers who care about quality and scalable architectures. Make sure you find the right one and they will be glad to find you.
Avoid the temptation to save your current team from their own short-sightedness. From your descriptions, it sounds like you are already a pariah despite your talents. Accept the fact that you won't be listened to.
The best strategy is to fake being a born-again team player. Build your MVC project exactly the way your boss has asked, i.e. the dumb way, with no separation of concerns. When version 1 of your project is finish and passes QA (if you have any QA), your boss will probably think he is vindicated. Be prepared for this reaction.
The best hope you have of enlightening your current team members is to show them that even if you build software using the same dumb practices they are comfortable with, you can still run rings around them. This can be fun. Then, when you leave, you give them a chance to reflect on the possibility that you were on to something. They can either take that chance or opt for continued comfort, but it won't be your problem any longer.

C++ & proper TDD

Hi! I recently tried developing a small-sized project in C# and during the whole project our team used the Test-Driven-Development (TDD) technique (xunit, moq).
I really think this was awesome, because (when paired with C#) this approach allowed to relax when coding, relax when projecting and relax when refactoring. I suspect that all this TDD-stuff actually simplifies the coding process and, well, it allowed (eventually, for me) to get the same result with fewer brain cells working.
Right after that I tried using TDD paired with C++ (I used Google Test and Google Mock libraries), and, I don't know why but I actually think that TDD here was a step back in terms of rapid application development.
I had some moments when I had to spend huge amounts of time thinking of my tests, building proper mocks, rebuilding them and swearing at my monitor.
And, well, I obviously can't ask something like "what I did wrong?" or "what was wrong in my approach?", because I don't know what to describe. But if there are any people who are used to TDD in C++ (and, probably C#) too, could you please advise me how to do this properly.
Framework recommendations, architecture approaches, plain coding advices - if you are experienced in TDD & C++, please respond.
I think TDD is much harder to do in C++ than C#. The lack of reflection, and the common (and often well-justified) reluctance to rely on dynamic polymorphism (interfaces and in heritance) compared to static polymorphism does make it harder to mock out many classes.
There are some extremely clever unit test frameworks for C++, but the thing that's so clever about them is mainly that they try to bypass the language limitations.
TDD works best in dynamic languages. It's a great way to work in Python. It's doable in C# (which isn't dynamic, but has comprehensive reflection capabilities)
In C++, it's often problematic. That doesn't mean it can't, or shouldn't, be done, but when you do it, expect to have to work a bit harder at it. And sometimes, you may be better off using another approach entirely.
TDD is something that takes some practice to get right, regardless of the platform. What some people don't seem to realize is that the nature of the problem your trying to solve can have a big impact on how easily you can apply TDD to the solution. I've had problems in the past where I knew the solution I wanted to move towards, but it was extremely difficult to figure out how to break the problem up in a way that seemed to fit the TDD model. Now there are several reasons why this may happen, and it's impossible to say what the "right" way to handle that situation is.
At this point my first reaction to running into this sort of problem is to re-examine my original assumptions about the problem. Am I making it more complex than it needs to be? Am I trying to write tests to arrive at a design I've already decided on instead of letting the tests guide the design? Is it just a funky problem, and I need to accept that the typical TDD approach isn't going to work in this case?
For an interesting discussion of this you can look at this blog post from Uncle Bob Martin, where he talks about an attempt by Ron Jeffries to create a Sudoku Solver using TDD, and it doesn't really work. Now because this attempt did not produce a good solution doesn't mean that TDD is useless, it just means that the problem being solved is more complex, and does not lend itself to the emergent design approach of TDD.
Try the easiest - CxxTest.
I find test driven development very hard to do properly all the time; sometimes the tests just flow, sometimes a bit of a jump is required. To keep things fast I frequently step away from the TDD approach. That isn't a problem for me as I maintain a full set of unit tests for all the code I've 'completed' (allowing the relaxation while coding the new bits and refactoring) .

Unit testing database application with business logic performed in the UI

I manage a rather large application (50k+ lines of code) by myself, and it manages some rather critical business actions. To describe the program simple, I would say it's a fancy UI with the ability to display and change data from the database, and it's managing around 1,000 rental units, and about 3k tenants and all the finances.
When I make changes, because it's so large of a code base, I sometimes break something somewhere else. I typically test it by going though the stuff I changed at the functional level (i.e. I run the program and work through the UI), but I can't test for every situation. That is why I want to get started with unit testing.
However, this isn't a true, three tier program with a database tier, a business tier, and a UI tier. A lot of the business logic is performed in the UI classes, and many things are done on events. To complicate things, everything is database driven, and I've not seen (so far) good suggestions on how to unit test database interactions.
How would be a good way to get started with unit testing for this application. Keep in mind. I've never done unit testing or TDD before. Should I rewrite it to remove the business logic from the UI classes (a lot of work)? Or is there a better way?
I would start by using some tool that would test the application through the UI. There are a number of tools that can be used to create test scripts that simulate the user clicking through the application.
I would also suggest that you start adding unit tests as you add pieces of new functionality. It is time consuming to create complete coverage once the appliction is developed, but if you do it incrementally then you distribute the effort.
We test database interactions by having a separate database that is used just for unit tests. In that way we have a static and controllable dataset so that requests and responses can be guaranteed. We then create c# code to simulate various scenarios. We use nUnit for this.
I'd highly recommend reading the article Working Effectively With Legacy Code. It describes a workable strategy for what you're trying to accomplish.
One option is this -- every time a bug comes up, write a test to help you find the bug and solve the problem. Make it such that the test will pass when the bug is fixed. Then, once the bug is resolved you have a tool that'll help you detect future changes that might impact the chunk of code you just fixed. Over time your test coverage will improve, and you can run your ever-growing test suite any time you make a potentially far-reaching change.
TDD implies that you build (and run) unit tests as you go along. For what you are trying to do - add unit tests after the fact - you may consider using something like Typemock (a commercial product).
Also, you may have built a system that does not lend itself to be unit tested, and in this case some (or a lot) of refactoring may be in order.
First, I would recommend reading a good book about unit testing, like The Art Of Unit Testing. In your case, it's a little late to perform Test Driven Development on your existing code, but if you want to write your unit tests around it, then here's what I would recommend:
Isolate the code you want to test into code libraries (if they're not already in libraries).
Write out the most common Use Case scenarios and translate them to an application that uses your code libraries.
Make sure your test program works as you expect it to.
Convert your test program into unit tests using a testing framework.
Get the green light. If not, then your unit tests are faulty (assuming your code libraries work) and you should do some debugging.
Increase the code and scenario coverage of your unit tests: What if you entered unexpected results?
Get the green light again. If the unit test fails, then it's likely that your code library does not support the extended scenario coverage, so it's refactoring time!
And for new code, I would suggest you try it using Test Driven Development.
Good luck (you'll need it!)
I'd recommend picking up the book Working Effectively with Legacy Code by Michael Feathers. This will show you many techniques for gradually increasing the test coverage in your codebase (and improving the design along the way).
Refactoring IS the better way. Even though the process is daunting you should definitely separate the presentation and business logic. You will not be able to write good unit tests against your biz logic until you make that separation. It's as simple as that.
In the refactoring process you will likely find bugs that you didn't even know existed and, by the end, be a much better programmer!
Also, once you refactor your code you'll notice that testing your db interactions will become much easier. You will be able write tests that perform actions like: "add new tenant" which will involve creating a mock tenant object and saving "him" to the db. For you next test you would write "GetTenant" and try and get that tenant that you just created from the db and into your in-memory representation... Then compare your first and second tenant to make sure all fields match values. Etc. etc.
I think it is always a good idea to separate your business logic from UI. There several benefits to this including easier unit testing and expandability. You might also want to refer to pattern based programming. Here is a link http://en.wikipedia.org/wiki/Design_pattern_(computer_science) that will help you understand design patterns.
One thing you could do for now, is within your UI classes isolate all the business logic and different business bases functions and than within each UI constructor or page_load have unit test calls that test each of the business functions. For improved readability you could apply #region tag around the business functions.
For your long term benefit, you should study design patterns. Pick a pattern that suits your project needs and redo your project using the design pattern.
It depends on the language you are using. But in general start with a simple testing class that uses some made up data(but still something 'real') to test your code with. Make it simulate what would happen in the app. If you are making a change in a particular part of the app write something that works before you change the code. Now since you have already written the code getting testing up is going to be quite a challenge when trying to test the entire app. I would suggest start small. But now as you write code, write unit testing first then write your code. You might also considering refactoring but I would weigh the costs of refactoring vs rewriting a little as you go unit testing along the way.
I haven't tried adding test for legacy applications since it is really a difficult chore. If you are planning to move some of the business logic out of the UI and in a separate layer, You may add your initial Test units here(refactoring and TDD). Doing so will give you an introduction for creating unit test for your system. It is really a lot of work but I guess it is the best place to start. Since it is a database driven application, I suggest that you use some mocking tools and DBunit tools while creating your test to simulate the database related issues.
There's no better way to get started unit testing than to try it - it doesn't take long, it's fun and addictive. But only if you're working on testable code.
However, if you try to learn unit testing by fixing an application like the one you've described all at once, you'll probably get frustrated and discouraged - and there's a good chance you'll just think unit testing is a waste of time.
I recommend downloading a unit testing framework, such as NUnit or XUnit.Net.
Most of these frameworks have online documentation that provides a brief introduction, like the NUnit Quick Start. Read that, then choose a simple, self-contained class that:
Has few or no dependencies on other classes - at least not on complex classes.
Has some behavior: a simple container with a bunch of properties won't really show you much about unit testing.
Try writing some tests to get good coverage on that class, then compile and run the tests.
Once you get the hang of that, start looking for opportunities to refactor your existing code, especially when adding new features or fixing bugs. When those refactorings lead to classes that meet the criteria above, write some tests for them. Once you get used to it, you can start by writing tests.

Applying Test Driven Development to a tightly coupled architecture

I've recently been studying TDD, attended a conference and have dabbled in few tests and already I'm 100% sold, I absolutely love it TDD.
As a result I've raised this with my seniors and they are prepared to give it a chance, so they have tasked me with coming up with a way to implement TDD in the development of our enterprise product.
The problem is our system has evolved since the days of VB6 to .NET and implements a lot of legacy technology and some far from best practice development techniques i.e. a lot of business logic in the ASP.NET code behind and client script. The largest problem however is how our classes are tightly coupled with database access; properties, methods, constructors - usually has some database access in some form or another.
We use an in-house data access code generator tool that creates sqlDataAdapters that gives us all the database access we could ever want, which helps us develop extremely quickly, however, classes in our business layer are very tightly coupled to this data layer - we aren't even close to implementing some form of repository design. This and the issues above have created me all sorts of problems.
I have tried to develop some unit tests for some existing classes I've already written but the tests take A LOT longer to run since db access is required, not to mention since we use the MS Enterprise Caching framework I am forced to fake a httpcontext for my tests to run successfully which isn't practical. Also, I can't see how to use TDD to drive the design of any new classes I write since they have to be so tightly coupled to the database ... help!
Because of the architecture of the system it appears I can't implement TDD without some real hack which in my eyes just defeats the aim of TDD and the huge benefits that come with.
Does anyone have any suggestions how I could implement TDD with the constraints I'm bound to? Or do I need to push the repository design pattern down my seniors throats and tell them we either change our architecture/development methodology or forget about TDD altogether? :)
Thanks
Just to clarify, Test driven development and unit testing are not the same thing.
TDD = Write your tests before your code.
Unit Testing = Writing tests that confirm a small unit of code works.
Integration Testing = Writing tests that confirm blocks of code work together.
TDD, by definition, can't be done on existing code. You've already developed the code, so you aren't going to develop it again. TDD means you first write a failing test, then you write just enough code to pass the test. You've already written the code, so you can't do TDD.
You can write unit tests for existing code but this isn't the same as doing TDD.
The tests you have described (accessing the database etc) are technically integration tests. Integration tests do usually take ages to run. A true unit test would purely test your DA layer code without actually accessing the database. True unit testing requires interfaces to test against so you can isolate units from the surrounding units.
It's very hard to properly unit test existing code, unless it's been well designed with interfaces and abstraction in mind.
I know I'm being slightly picky with terminology here, but it's important when it comes to what approach you can take. My advice would be that with existing code that isn't well abstracted you should gradually build up a suite of automated integration tests. When you come to write something new (Which may not be a whole project, it may just be a new part to the existing app), consider approaching it in a TDD style. To do this you will find that you need to write some interfaces and abstractions to allow you to do TDD on your new code without triggering too much of the existing code. You will then be able to write some more integration tests that test your new code working with the old code.
To cut it short - don't try and change methodology for existing code. Just do new code better.
Nitpick: you can't do Test-Driven Design on existing code, but I do realize that you wish to use TDD against new functionality you implement on the existing code base.
The best thing you can do is to gradually introduce seams into the code base, shielding you from the tightly coupled code already in existence.
The book Working Effectively with Legacy Code contains much good advice on how to turn a legacy application into a testable application.
I think the mere fact that you are using ASP.NET Web Forms your road to TDD will be challenged. It's just a nightmare to mock the Session/ViewState/HTTPContext in Web Forms so test-driven is almost a hindrance. There is of course the ASP.NET MVC alternative, but you're way down the road already it seems. Another promising option for the Web Forms paradigm is ASP.NET Web Forms MVP, but that project is really not fully mature yet. I'm moving everything I can to MVC; the other option for TDD with Web Forms, Selenium, isn't really TDD as it should be.
For adding tests to your existing code, you might check out Working Effectively With Legacy Code. "Legacy code" is defined as code that does not have tests in it.

How to Refactor to Generics from Class that Inherits from CollectionBase?

I am working on an application that is about 250,000 lines of code. I'm currently the only developer working on this application that was originally built in .NET 1.1. Pervasive throughout is a class that inherits from CollectionBase. All database collections inherit from this class. I am considering refactoring to inherit from the generic collection List instead. Needless to say, Martin Fowler's Refactoring book has no suggestions. Should I attempt this refactor? If so, what is the best way to tackle this refactor?
And yes, there are unit tests throughout, but no QA team.
Don't. Unless you have a really good business justification for putting your code base through this exercise. What is the cost savings or revenue generated by your refactor? If I were your manager I would probably advise against it. Sorry.
How exposed is CollectionBase from the inherited class?
Are there things that Generics could do better than CollectionBase?
I mean this class is heavily used, but it is only one class. Key to refactoring is not disturbing the program's status quo. The class should always maintain its contract with the outside world. If you can do this, it's not a quarter million lines of code you are refactoring, but maybe only 2500 (random guess, I have no idea how big this class is).
But if there is a lot of exposure from this class, you may have to instead treat that exposure as the contract and try and factor out the exposure.
If you are going to go through with it, don't use List< T >. Instead, use System.Collections.ObjectModel.Collection< T >, which is more of a spirtual succesor to CollectionBase.
The Collection<T> class provides protected methods that can be used to customize its behavior when adding and removing items, clearing the collection, or setting the value of an existing item. If you use List<T> there's no way to override the Add() method to handle when someone ads to the collection.
250,000 Lines is alot to refactor, plus you should take into account several of the follow:
Do you have a QA department that will be able to QA the refactored code?
Do you have unit tests for the old code?
Is there a timeframe that is around the project, i.e. are you maintaining the code as users are finding bugs?
if you answered 1 and 2 no, I would first and foremost write unit tests for the existing code. Make them extensive and thorough. Once you have those in place, branch a version, and start refactoring. The unit tests should be able to help you refactor in the generics in correctly.
If 2 is yes, then just branch and start refactoring, relying on those unit tests.
A QA department would help a lot as well, since you can field them the new code to test.
And lastly, if clients/users are needing bugs fixed, fix them first.
I think refactoring and keeping your code up to date is a very important process to avoid code rot/smell. A lot of developers suffer from either being married to their code or just not confident enough in their unit tests to be able to rip things apart and clean it up and do it right.
If you don't take the time to clean it up and make the code better, you'll regret it in the long run because you have to maintain that code for many years to come, or whoever takes over the code will hate you. You said you have unit tests and you should be able to trust those tests to make sure that when you refactor the code it'll still work.
So I say do it, clean it up, make it beautiful. If you aren't confident that your unit tests can handle the refactor, write some more.
I agree with Thomas.
I feel the question you should always ask yourself when refactoring is "What do I gain by doing this vs doing something else with my time?" The answer can be many things, from increasing maintainability to better performance, but it will always come at the expense of something else.
Without seeing the code it's hard for me to tell, but this sounds like a very bad situation to be refactoring in. Tests are good, but they aren't fool-proof. All it takes is for one of them to have a bad assumption, and your refactor could introduce a nasty bug. And with no QA to catch it, that would not be good.
I'm also personally a little leary of massive refactors like this. Cost me a job once. It was my first job outside of the government (which tends to be a little more forgiving, once you get 'tenure' it's damn hard to get fired) and I was the sole web programmer. I got a legacy ASP app that was poorly written dropped in my lap. My first priority was to get the darn thing refactored into something less...icky. My employer wanted the fires put out and nothing more. Six months later I was looking for work again :p Moral of this story: Check with your manager first before embarking on this.

Categories