Wednesday, 12 December 2012
Bananas and Monkeys
Ok first off, I did not write this, but damn it has some truth. For acknowledgement here is the link I found it on. It goes something like this...
Start with a cage containing five monkeys.
Inside the cage, hang a banana on a string and place a set of stairs under it. Before long, a monkey will go to the stairs and start to climb towards the banana. As soon as he touches the stairs, spray all of the other monkeys with cold water.
After a while, another monkey makes an attempt with the same result - all the other monkeys are sprayed with cold water. Pretty soon, when another monkey tries to climb the stairs, the other monkeys will try to prevent it.
Now, put away the cold water. Remove one monkey from the cage and replace it with a new one. The new monkey sees the banana and wants to climb the stairs. To his surprise and horror, all of the other monkeys attack him.
After another attempt and attack, he knows that if he tries to climb the stairs, he will be assaulted.
Next, remove another of the original five monkeys and replace it with a new one. The newcomer goes to the stairs and is attacked. The previous newcomer takes part in the punishment with enthusiasm! Likewise, replace a third original monkey with a new one, then a fourth, then the fifth. Every time the newest monkey takes to the stairs, he is attacked.
Most of the monkeys that are beating him have no idea why they were not permitted to climb the stairs or why they are participating in the beating of the newest monkey.
After replacing all the original monkeys, none of the remaining monkeys have ever been sprayed with cold water. Nevertheless, no monkey ever again approaches the stairs to try for the banana. Why not? Because as far as they know that's the way it's always been done round here.
And that, my friends, is how company policies are made.
Interesting huh?
Tuesday, 4 December 2012
NHibernate, Ninject 3, MVC 4
Recently I have started to use Ninject more and more, its my favourite of all the IOC frameworks I have used so far. Also I wanted to give MVC 4 a dabble just to keep myself in the loop with what is going on in the MVC world after only using MVC 2 in the past. So I thought I would try to wire up something nice between MVC4, Ninject 3 and NHibernate and came up with the following located on github here.
So in a previous post with NHibernate, Unit of Work, Repository and Structuremap, I carped on about a Unit of Work and a Repository.
Architecting in the pit of doom: The evils of the repository abstraction layer
Repository is the new singleton pattern
So in a previous post with NHibernate, Unit of Work, Repository and Structuremap, I carped on about a Unit of Work and a Repository.
With regards to the repository...
I think I have gone off the idea of using the Repository pattern with NHibernate after reading lots of posts on Ayende's site, various other sites and from previous experience I feel it is limiting NHibernate to make optimal calls to the database. I believe NHibernate's Session is the repository. Here are a couple of links:Architecting in the pit of doom: The evils of the repository abstraction layer
Repository is the new singleton pattern
With regards to the Unit of Work...
Here I just set up a filter to wrap up the work done across a transaction. So now any of the work in the domain model/business logic that is done via a particular controller action should all be wrapped up in a transaction. I wired up the filter using the Ninject.MVC3 extension and the Kernel.BindFilter.
Github project...
Its been a while since I looked at this project and what I was doing, so I will need to refresh myself with it as well. I just created the default MVC 4 app and added a new controller, the ProductController. I just wanted to be able to show a list of Products that are stored in the database and also be able to add new products and render the change.
Libraries I used:
MVC 4
Ninject 3
Ninject.MVC 3 extension
NHibernate
Automapper
The project isn't finished yet, I would like to try to wire up NServiceBus and RavenDB in here too (but these are just distance thoughts for the moment), and really push all the business logic down into the domain model.
Some points on what I did.
- Created the standard ASP.NET MVC 4 application.
- Added NHibernate and created a simple database relationship for stores, products and employees, I may have taken these relationships from somewhere else but I can't remember.
- Added Ninject and its Ninject.MVC 3 extension, this works for MVC 4.
That's it for now... I will come back and update this some more when I get a chance...
Monday, 26 November 2012
Programming is not just programming
Well its been a very long time since I posted something here, but today I had an idea of what I could write about...
I had a very good friend ask me about .net development, and that he was concerned about getting his .net skills up to scratch. My immediate thought was this guy is a super bright guy and I am sure he knows enough of .net to be able to do pretty much anything that was required of him and quickly as well. Which then led me onto thinking of this post and what I could write about.
I would say that a lot of .net developers out there know how to write code in .net and probably/possibly many other languages too, but possibly miss the idea of writing code that can be maintained and also feel confident about being maintained quickly (this does not mean that the super bright guy above does not know this :-)).
I would say of those that don't care and don't even realise what they are writing, their code is becoming legacy code as quickly as they type it. I for one was one of these guys (the didn't realise one), absolutely 100% omg! Am I admitting that! We all have to start somewhere (that's my excuse ;-) ) and from there its a lot of practice and realisation of what we are writing.
Now I am making a concentrated effort on everything I write to be much clearer, simpler, easier to understand and change, by keeping in mind as many of the things I have read about in the following books, links, blog posts frameworks etc.
I will try to keep this up to date every time I discover something new or useful. Lots of links and lots to digest I know, but it has taken me some time. Just take your time, practice a few things, try them out on some scratch projects see what you can come up with. You'll surprise yourself on how your code becomes much more awesome!
I had a very good friend ask me about .net development, and that he was concerned about getting his .net skills up to scratch. My immediate thought was this guy is a super bright guy and I am sure he knows enough of .net to be able to do pretty much anything that was required of him and quickly as well. Which then led me onto thinking of this post and what I could write about.
I would say that a lot of .net developers out there know how to write code in .net and probably/possibly many other languages too, but possibly miss the idea of writing code that can be maintained and also feel confident about being maintained quickly (this does not mean that the super bright guy above does not know this :-)).
I would say of those that don't care and don't even realise what they are writing, their code is becoming legacy code as quickly as they type it. I for one was one of these guys (the didn't realise one), absolutely 100% omg! Am I admitting that! We all have to start somewhere (that's my excuse ;-) ) and from there its a lot of practice and realisation of what we are writing.
Now I am making a concentrated effort on everything I write to be much clearer, simpler, easier to understand and change, by keeping in mind as many of the things I have read about in the following books, links, blog posts frameworks etc.
I will try to keep this up to date every time I discover something new or useful. Lots of links and lots to digest I know, but it has taken me some time. Just take your time, practice a few things, try them out on some scratch projects see what you can come up with. You'll surprise yourself on how your code becomes much more awesome!
- S.O.L.I.D - A must for every OO developer, probably any other link on that page too.
- Tell Dont Ask - Another nice one that can lead you onto the other nice things like CQRS and Law of Demeter
- Dependency Injection Stack Overflow link and James Shore Link from the same SO link - Lots of Inversion of Control (IOC) containers out there to help with this too. Ninject (my favourite), StructureMap, Unity, there are also more. I find this is really important and should be used on every project regardless of size of the project, what you will start to realise when you use this that your unit testing becomes easier to write.
- Unit Testing - There are many unit test frameworks out there to pick from, NUnit (I have used a lot), XUnit (but heard a lot of good things about this and I think I will start to use this for some home projects ), MSTest (Microsoft's, included with Visual Studio). Just a quick side note I would like to write an article about is Unit Testing. I believe and found it so difficult to start writing unit tests, this is also a lot of practice and when you realise how it fits and what it does, BOOM! It will be a Eureka moment!
- Resharper, get it! It's worth it! It has some very nice tools with it, the solution wide analysis(dont need to waste time building solution to find errors), the stack trace viewer are a couple. I recommend learning a shortcut a day, and within no time you wont need your mouse to code. Pffff, the amount of times I have sat there with someone using the mouse to click on menus, scrolling around, switching windows, looking for code in a solution, blah blah, all that time wasted.... aaarrrrgggghhhhh! Drives me nuts! Mind you I can get some 5 second power naps, when they are searching for the next thing to click! lol ;-)
- Read blogs articles, follow some recognised people, like some of the people from the books I have mentioned. Also take a look at some code you have found on github, contribute maybe too, you will learn so much like this.
- Go to some talks, organised day events, local newsgroups in your area, etc. skillsmatter, DDD
Ok some other stuff, buzz words, people, software etc... I will try to write these more in depth at some point but it will be worth you guys having a sniff at what they are about also.
Continuous Integration
Setting up a build and release process just off a single check in! If you can get this right, this is one of the most powerful things in releasing software fast and reducing all that wasted time, matching up bugs with changesets, with releases, deploying the correct version for your testers, unit testing, integration testing etc. A couple more pieces of software provided from JetBrains, TeamCity and YouTrack is worth taking a look at also, extremely useful for tracking all task, bugs etc. There are many other solutions out there too, but these are the first that came to mind for the moment.
Source Control
There are several source control systems out there, here are a few...
- GIT - Extremely powerful and gives much more ease and freedom for your code. I have only started to use this recently, it takes a little time to get your head around if you are used to using a more centralised system, here are some links... GIT Succinctly, GitHub get an account, try it out, practice, stick at it. Well worth it!
- TFS - Microsoft's version of source control, along with managing tasks and probably other things too. I use it most of my working time. But the more I use GIT the less I want to use this.
- SVN - Not used in a long time and used sporadically.
- SourceSafe - This has to get a mention! DO NOT USE IT!! REALLY! DON'T! Go take a read of any articles about it, see what people have to say about it, maybe you have had your own experiences with it...
Database Stuff
Apart from the usual same old boring databases are databases blurb, blah blah, same old, same old, SQL Server, MySQL, PostgreSQL, blah blah etc ooops forgot about Oracle.
But there are these new document databases turning up, which seem very very interesting, take a look, try them out, RavenDB and MongoDB. I haven't used them yet, but will be giving them a go soon I hope. They seem extremely powerful and fast. I went to a see Oren Eini and he gave an excellent talk on RavenDB. Interesting thoughts of why now we should be looking at storing and retrieving data differently.
Books
- Working Effectively With Legacy Code - Michael Feathers, Don't be depressed with crap code, take a read of this and see how you can fix it! Very good read and interesting.
- Clean Code, and The Clean Coder - Robert C. Martin (Uncle Bob), Both these books very nice.
- Refactoring: Improving the Design of Existing Code. Excellent! Nice techniques, mixing this with Michael Feathers book above and the Clean Coding books of Uncle Bob you will have some quite powerful ways of being able to modify the most complex of code.
- The Pragmatic Programmer: From Journeyman to Master - Andrew Hunt and David Thomas, Superb, must read for all developers! Interesting too, see if you can recognise any of your situations you have been in match whats in this book, I wouldn't be surprised most of them match :-)
- The Art of Unit Testing - Roy Osherove, Very nice, a definite good start with Unit Testing, but I still think you need to practice and see what it really is worth.
- C# In Depth - Jon Skeet, Superb! I have to take my time in this one, and probably have to read it a few times, but excellent!
- Domain Drive Design: Tackling Complexity in the Heart of Software - Eric Evans, I have started reading it but not got very far yet, but heard it is very good.
Other Things
- Rx - A must! Take a look! Try it out! See what you can do and learn from this. Very powerful!
- Agile - I would say a very powerful, fast and useful process of writing software. I would never go back to Waterfall again if I could help it, unless I needed money for sleeping. I haven't read up much on the agile processes but been in the flow of using this style of development with several projects.
- NServiceBus - I haven't used yet but all I hear is good things about this piece of software check it out. I will be trying this out in the near future also.
- Automapper - For transfering data from one object to another which has the same properties, Very neat, very useful, easy to use, set up.
- Some people, Martin Fowler, Kent Beck, Robert C. Martin (Uncle Bob), Oren Eini, Udi Dahan, Jon Skeet, all of these have a massive community around them and well worth reading up some of their articles.
Saturday, 9 July 2011
Is Switch by definition a Code Smell?
I am fed up of coming across this kind of shite code all the time, whenever I need to fix a bug I need to change 400 things not 1 thing.
It’s absolutely nonsense!! We are using an object orientated language ffs! Can we not see the impact of the problems this kind of code leads too?
What’s it there for, are you going to create another manager from the same interface(highly unlikely)? Is it there for the Dependency Injection instead? Then I am sure you can inject it without an interface. Even if you’re going down this road asking yourself these questions, you may realise 'ooo' the code is in the wrong place and we shouldn’t have Managers and Helpers littered everywhere! And this is another post all in itself (Say NO to managers/Helpers)
Throwing an exception if the type doesn’t exists is also crap!
I mean seriously if you were testing this and for some reason you never hit this if/switch statement after adding your new type, that exception will never be thrown!! Oh yes and I guarantee it will be thrown when a user uses it!
Here is a link I found very quickly (I am not sure who it is by) on the issue there is a lot of info here and was hoping to find something by the main man himself Martin Fowler who we should all know and love! It pretty much goes over a lot of issues with using a switch (or ifs in our case from this code, it’s the same thing) in an OO language. IMO we should be able to turn the ‘switch’ and ‘if’ statements OFF in the compiler and to be only allowed to turn them on where we need them, more than likely in the Domain Model Entities only!
I can’t stress how important something as simple as this is, It’s a simple piece of code and if thought about for at least 30 seconds, the problem could be solved much more elegantly and safely. If you’re unsure on something don’t hesitate to ask the question to a colleague. I don’t have all the answers but I can see some of them. Just by asking the question sometimes you actually answer it yourself without hearing an answer (I do that a LOT).
If this doesn’t seem to be an important issue to you and want to continue to switch and if on types I am sure there are plenty of job opportunities out there as a farmer! Let us developers write robust code and not fix someone else's problems all the time.
22 public class CrapiolaManager : ICrapiolaManager
23 {
24 public void DoSomething(SomeEnumOfTypesWtf someType)
25 {
26 if (someType == SomeEnumOfTypesWtf.SomeType1)
27 {
28 //1. Do some work and calculations etc and more crap code...
29 }
30 if (someType == SomeEnumOfTypesWtf.SomeType2)
31 {
32 //2. Do some work and calculations etc and more crap code...
33 }
34 if (someType == SomeEnumOfTypesWtf.SomeType3)
35 {
36 //3. Do some work and calculations etc and more crap code...
37 }
38 if (someType == SomeEnumOfTypesWtf.SomeType4)
39 {
40 //4. Do some work and calculations etc and more crap code...
41 }
42 if (someType == SomeEnumOfTypesWtf.SomeType5)
43 {
44 //5. Do some work and calculations etc and more crap code...
45 }
46
47 throw new InvalidOperationException("Invalid type passed");
48 }
49 }
- Lots of bugs/issues!!!
- New stories take longer to do!!!
- Its duplication of code!
- It’s not easy to Test!!
- Not easy to read when you have to follow code through so many layers, you want a piece of logic in ONE place… Domain Model Entity?
- It’s a problem when a new type appears! Somehow the person working on the new type needs to magically pull out of his ass some knowledge to understand where all the switch’s and if’s are in the code to alter them to add a new case! Hmmm… I wonder how many of these if’s and switch’s get missed when adding a new type? Oooo let me guess… ALL OF THEM! It’s completely unmaintainable rubbish!
What’s it there for, are you going to create another manager from the same interface(highly unlikely)? Is it there for the Dependency Injection instead? Then I am sure you can inject it without an interface. Even if you’re going down this road asking yourself these questions, you may realise 'ooo' the code is in the wrong place and we shouldn’t have Managers and Helpers littered everywhere! And this is another post all in itself (Say NO to managers/Helpers)
Throwing an exception if the type doesn’t exists is also crap!
I mean seriously if you were testing this and for some reason you never hit this if/switch statement after adding your new type, that exception will never be thrown!! Oh yes and I guarantee it will be thrown when a user uses it!
- BIG Problem!
- Support costs!
- Customer trust levels!
- The list carries on…
A suggestion to resolve this problem! (Not too much detail here)
(This is the basics of the start of the fix but should pretty much be an answer for this issue). Hmmm… how about use an interface or a base class (depending on what you require) and derive these types from that interface/base class to force implementation of the method that does the work in them dumb ass if’s and switch’s! It takes 2 minutes to write, and NOT 2 days to fix bugs when adding new types!
22 public interface IDoSomething
23 {
24 void DoSomething();
25 }
26
27 public class DoSomehting1 : IDoSomething
28 {
29 public void DoSomething()
30 {
31 //1. Do some work and calculations etc and more crap code...
32 }
33 }
34 public class DoSomehting2 : IDoSomething
35 {
36 public void DoSomething()
37 {
38 //2. Do some work and calculations etc and more crap code...
39 }
40 }
41 public class DoSomehting3 : IDoSomething
42 {
43 public void DoSomething()
44 {
45 //3. Do some work and calculations etc and more crap code...
46 }
47 }
48 ...
49 public class DoTheWork
50 {
51 public void Work(IDoSomething doSomething)
52 {
53 //The object does the work not some external object that would be a nightmare to maintain.
54 doSomething.DoSomething();
55
56 //The above is called instead of doing...
57 //ICrapiolaManager someManager;
58 //someManager.DoSomething();
59 }
60 }
It’s not all about finishing as fast as possible and just letting your fingers typing your brain farts for 100% of the day, surprisingly it’s a very high amount of THINKING! The chances are when you come to the solution in your head after thinking around all the issues, scenarios and solutions to the problem you will find you will hardly type any code!
Here is a link I found very quickly (I am not sure who it is by) on the issue there is a lot of info here and was hoping to find something by the main man himself Martin Fowler who we should all know and love! It pretty much goes over a lot of issues with using a switch (or ifs in our case from this code, it’s the same thing) in an OO language. IMO we should be able to turn the ‘switch’ and ‘if’ statements OFF in the compiler and to be only allowed to turn them on where we need them, more than likely in the Domain Model Entities only!
I can’t stress how important something as simple as this is, It’s a simple piece of code and if thought about for at least 30 seconds, the problem could be solved much more elegantly and safely. If you’re unsure on something don’t hesitate to ask the question to a colleague. I don’t have all the answers but I can see some of them. Just by asking the question sometimes you actually answer it yourself without hearing an answer (I do that a LOT).
If this doesn’t seem to be an important issue to you and want to continue to switch and if on types I am sure there are plenty of job opportunities out there as a farmer! Let us developers write robust code and not fix someone else's problems all the time.
Monday, 7 March 2011
Nhibernate, Unit Of Work, Repository and StructureMap
This could be a long blog...
Well I have spent some time recently trying to understand how to tie all this lot together and I think I have finally cracked it in its simplest form, I am hoping at least. This is my first stab at it and I am already thinking of changing it slightly, but I want to show what I did first.
If there is anything you don't like on here or want to question please come and comment as I would love to get some feedback on what people thought of this. Problematic, see problems with it or even helped to understand it better.
NHibernate
So first of all I modelled a simple domain, just an account user and mapped this to NHibernate to do its thing with the db. Understood then that the NHibernate's SessionFactory should be once per application as its very expensive to create and that ISession is what to use every time you want to make a single or group of changes to the db, or to just retrieve anything.
Code that I Wanted/Needed
So the following are the general things I used and set up simply as possible for now.
Repository
First off I read up loads of articles on creating a repository to wrap up simple NHibernate commands. This could be extended in the future to provide a more advanced implementation. Some would argue not to have the repository at all and use the NHibernate calls directly. I like the idea of keeping the repository implementation as I am hoping it decouples NHibernate from the application (don't know why I will ever need to not use NHibernate yet but its there). I would like to be able to create as many of these as I would like although at the moment I am unsure why I would need more than 1 per thread. This will contain a UnitOfWork.
UnitOfWork
This implements IDisposable and is what I used to manage the transaction of the NHibernate session. I would like it to dispose of the session once its been commited or rolledback, it just has a simple commit and rollback and manages to close the session. The session and transaction is created in the constructor here, so the UnitOfWork is ready to be commited or rolledback. The more I am typing here the more I am feeling this class is clunky around the edges of cleaning up. I am not sure if I need to rollback the transaction by default in the dispose if its active already, or whether the Session manages maintains that on a dispose of itself? If anyone knows let me know :-)
As you can probably see there is no creation of the interfaces SessionFactory or UnitOfWork in repository and this is where I have used StructureMap to help out.
StructureMap
I went the Ninject route initially as it had a cool looking site and seemed quite nice to use also. I managed to achieve what I wanted with it and it wasn't difficult at all but I wont show that here. I researched further into which DI/IOC to use and I kind of had a good feel for what people were saying about StructureMap so I changed to use StructureMap instead.
OK so I figured I needed
So in here, I am setting up the
I will try and show a couple of tests that I set up for this, and show how it could be used from the outside. I hope my tests aren't too bad, I know I find it difficult to write a good test, come slate them let me know what you would do, naming them something different? anything? I need to learn more about tests.
Test to write data to the database was successful.
so this test was to tell me that I could write more than 1 thing to the database at the same time on the same UnitOfWork. I did use the nhibernate profiler to spy on a little of what was going on here, which may I add is superb, easy to use, understand and set up. Going back to the test though, the UnitOfWork and StructureMap did their job nicely and only created one of them. One UnitOfWork was created as part of the 'using' and the one that was injected into the Repository creation (on line 74 of the test) was the same one. Superb! The data was added, the UnitOfWork commited and job done. I cleared the session at this point to force nhibernate to fetch the data from the database again rather than retrieve it from its cache.
Test to prove that there was a different UnitOfWork created when created in another thread.
with this test I am thinking along the lines I could use the UnitOfWork per HttpRequest using MVC some where along the lines, creating the UnitofWork in ActionExecting maybe and the commit/rollback on what ever the opposite one is. When I get to working that out I will post that next I think.
Changes I would like to make for an MVC web application.
I will get round to bloging what I did for this, but for short I am considering removing the UnitOfWork and Repository all together and let StructureMap create the Session and inject it into the controller constructors when they are created, but my only hesitation in this is that it will couple NHibernate to the controllers as they will need an ISession injected into them and also need to manage the Transaction.
Well I have spent some time recently trying to understand how to tie all this lot together and I think I have finally cracked it in its simplest form, I am hoping at least. This is my first stab at it and I am already thinking of changing it slightly, but I want to show what I did first.
If there is anything you don't like on here or want to question please come and comment as I would love to get some feedback on what people thought of this. Problematic, see problems with it or even helped to understand it better.
NHibernate
So first of all I modelled a simple domain, just an account user and mapped this to NHibernate to do its thing with the db. Understood then that the NHibernate's SessionFactory should be once per application as its very expensive to create and that ISession is what to use every time you want to make a single or group of changes to the db, or to just retrieve anything.
Code that I Wanted/Needed
So the following are the general things I used and set up simply as possible for now.
Repository
First off I read up loads of articles on creating a repository to wrap up simple NHibernate commands. This could be extended in the future to provide a more advanced implementation. Some would argue not to have the repository at all and use the NHibernate calls directly. I like the idea of keeping the repository implementation as I am hoping it decouples NHibernate from the application (don't know why I will ever need to not use NHibernate yet but its there). I would like to be able to create as many of these as I would like although at the moment I am unsure why I would need more than 1 per thread. This will contain a UnitOfWork.
5 class Repository : IRepository
6 {
7 readonly IUnitOfWork _unitOfWork;
8
9 public Repository(IUnitOfWork unitOfWork)
10 {
11 _unitOfWork = unitOfWork;
12 }
13
14 #region IRepository<AccountUser> Members
15
16 public T GetById<T>(Guid id)
17 {
18 return _unitOfWork.CurrentSession.Get<T>(id);
19 }
20
21 public void Add<T>(T entity)
22 {
23 _unitOfWork.CurrentSession.SaveOrUpdate(entity);
24 }
25
26 public void Remove<T>(T entity)
27 {
28 _unitOfWork.CurrentSession.Delete(entity);
29 }
30
31 #endregion
32 }
UnitOfWork
This implements IDisposable and is what I used to manage the transaction of the NHibernate session. I would like it to dispose of the session once its been commited or rolledback, it just has a simple commit and rollback and manages to close the session. The session and transaction is created in the constructor here, so the UnitOfWork is ready to be commited or rolledback. The more I am typing here the more I am feeling this class is clunky around the edges of cleaning up. I am not sure if I need to rollback the transaction by default in the dispose if its active already, or whether the Session manages maintains that on a dispose of itself? If anyone knows let me know :-)
6 public class UnitOfWork : IUnitOfWork
7 {
8 private readonly ISessionFactory _sessionFactory;
9 private ISession _currentSession;
10 private readonly ITransaction _currentTransaction;
11
12 public UnitOfWork(ISessionFactory sessionFactory)
13 {
14 _sessionFactory = sessionFactory;
15 _currentTransaction = CurrentSession.BeginTransaction();
16 }
17
18 #region IUnitOfWork Members
19
20 public ISession CurrentSession
21 {
22 get { return _currentSession ?? (_currentSession = _sessionFactory.OpenSession()); }
23 }
24
25 protected ITransaction BeginTransaction()
26 {
27 return _currentSession.BeginTransaction();
28 }
29
30 public void Commit()
31 {
32 if (_currentTransaction.IsActive)
33 _currentTransaction.Commit();
34 }
35 public void Rollback()
36 {
37 if (_currentTransaction.IsActive)
38 _currentTransaction.Rollback();
39 }
40
41 #endregion
42
43 #region IDisposable Members
44
45 public void Dispose()
46 {
47 if (_currentSession == null) return;
48
49 _currentSession.Dispose();
50 _currentSession = null;
51 }
52
53 #endregion
54 }
As you can probably see there is no creation of the interfaces SessionFactory or UnitOfWork in repository and this is where I have used StructureMap to help out.
StructureMap
I went the Ninject route initially as it had a cool looking site and seemed quite nice to use also. I managed to achieve what I wanted with it and it wasn't difficult at all but I wont show that here. I researched further into which DI/IOC to use and I kind of had a good feel for what people were saying about StructureMap so I changed to use StructureMap instead.
OK so I figured I needed
- 1 SessionFactory per application running.
- 1 UnitOfWork per thread running.
- No limit to the number of Repositories. (not sure why this can't be 1 instance per thread also but I don't think there is harm in having more than 1 as it will use the same UnitOfWork if its in the same thread.)
9 public static class ContainerBootstrapper
10 {
11 public static void BootstrapStructureMap()
12 {
13 ObjectFactory.Initialize(x =>
14 {
15 x.ForSingletonOf<ISessionFactory>().UseSpecial(y =>
16 y.ConstructedBy(context =>
17 {
18 var nhConfig = Fluently
19 .Configure()
20 .Database(MsSqlConfiguration
21 .MsSql2008
22 .ConnectionString(connstr =>
23 connstr.FromConnectionStringWithKey("db")))
24 .Mappings(mappings => mappings
25 .FluentMappings
26 .AddFromAssemblyOf<AccountUser>())
27 .BuildConfiguration();
28
29 return nhConfig.BuildSessionFactory();
30 }));
31 x.For<IUnitOfWork>().HybridHttpOrThreadLocalScoped().Use<UnitOfWork>();
32 x.For<IRepository>().Use<Repository>();
33 });
34 }
35 }
- 1 single SessionFactory ever for the application. The x.ForSingletonOf<ISessionFactory> will sort this out. It uses the Fluent style configuration of the sessionFactory using the database connection and mappings from the domain model set up.
- Per thread UnitOfWork, we want this as we may have more than 1 save, update and delete on the same transaction, so when its injected into the repository its the same UnitOfWork that is used before the repository has begun to be used, I will show a test later on with this.
- Repository.
I will try and show a couple of tests that I set up for this, and show how it could be used from the outside. I hope my tests aren't too bad, I know I find it difficult to write a good test, come slate them let me know what you would do, naming them something different? anything? I need to learn more about tests.
Test to write data to the database was successful.
67 [TestMethod]
68 public void Can_SaveSomeUserDataViaStructureMap()
69 {
70 ContainerBootstrapper.BootstrapStructureMap();
71
72 using (var uoW = ObjectFactory.GetInstance<IUnitOfWork>())
73 {
74 var repo = ObjectFactory.GetInstance<IRepository>();
75 var newUser = new AccountUser
76 {
77 Name = "Test",
78 Email = "Email Test",
79 Password = "Password Test"
80 };
81 var newUser2 = new AccountUser
82 {
83 Name = "Test2",
84 Email = "Email Test",
85 Password = "Password Test"
86 };
87 repo.Add(newUser);
88 repo.Add(newUser2);
89
90 uoW.Commit();
91
92 //Clear the session so its forced to go to the database and not pull from the cache
93 uoW.CurrentSession.Clear();
94
95 var returnedAccountUser = repo.GetById<AccountUser>(newUser.Id);
96 Assert.AreEqual("Test", returnedAccountUser.Name, "Failed to get user from database.");
97 }
98 }
so this test was to tell me that I could write more than 1 thing to the database at the same time on the same UnitOfWork. I did use the nhibernate profiler to spy on a little of what was going on here, which may I add is superb, easy to use, understand and set up. Going back to the test though, the UnitOfWork and StructureMap did their job nicely and only created one of them. One UnitOfWork was created as part of the 'using' and the one that was injected into the Repository creation (on line 74 of the test) was the same one. Superb! The data was added, the UnitOfWork commited and job done. I cleared the session at this point to force nhibernate to fetch the data from the database again rather than retrieve it from its cache.
Test to prove that there was a different UnitOfWork created when created in another thread.
110 [TestMethod]
111 public void Must_HaveNewSessionPerUoWPerThread()
112 {
113 ContainerBootstrapper.BootstrapStructureMap();
114 //Create this instance on this thread.
115 var uoW = ObjectFactory.GetInstance<IUnitOfWork>();
116 IUnitOfWork uoW2;
117
118 var thread = new Thread(x =>
119 {
120 uoW2 = ObjectFactory.GetInstance<IUnitOfWork>();
121 Assert.AreNotSame(uoW, uoW2);
122 Assert.AreNotSame(uoW.CurrentSession, uoW2.CurrentSession);
123 });
124 thread.Start();
125 }
Changes I would like to make for an MVC web application.
I will get round to bloging what I did for this, but for short I am considering removing the UnitOfWork and Repository all together and let StructureMap create the Session and inject it into the controller constructors when they are created, but my only hesitation in this is that it will couple NHibernate to the controllers as they will need an ISession injected into them and also need to manage the Transaction.
Subscribe to:
Posts (Atom)