I’m happy to report that the latest installment in the Autumn of Agile screencast series is now available for immediate download from the main site.
Refactoring to Eliminate Technical Debt
In this screencast, we take some time to do some (minor) refactorings to start to pay down some technical debt that we’ve started to incur in the project. It may seem strange to worry about technical debt before we’ve even finished our first user story(!) but from experience I have learned that its never too soon to start incurring technical debt and so its never too soon to start to spend some effort paying it down either. If you let it get ahead of you, many projects never manage to entirely recover.
Time more under Control
I did manage to solve another of my problems with this installment: its length is back under control . This screencast clocks in at a more manageable 1:45 or so and while others have indicated that length isn’t a concern for them, for my own sanity I would prefer that these by kept to a more reasonable length (where possible).
I have (mostly) put to bed my concerns that the length of these will be prohibitive for viewers, but that obviously doesn’t mean that I’m going to make them long just for the sake of it.
Still Covered A Lot
Despite the short(er) length, we still managed to cover quite a bit of territory in this installment including…
- understanding some pitfalls of just accepting Windsor’s default Singleton lifecycle for its objects
- refactoring our component registrations in the container to leverage the Windsor fluent Registration API
- identifying that 9 out of 10 times you think you’ve found a bug in someone else’s framework it really means its time to look much more closely at your own work (to see where you went wrong!)
- changing the behavior of the AddSkills(…) method on our Employee object to handle trying to add duplicate skills
- finally closing our first user story (yay!)
- evaluating our burn-down rate to predict when TargetProcess thinks we will be (finally) done with the project based on present iteration velocity
- Our first retrospective
- Getting set for Iteration 02
As always, questions, comments, and other feedback are welcome.
thanks a lot Steve.
If end users are concerned about the length of the screencasts – there’s a “fast play” option in Windows Media Player. Select Play –> Play Speed –> Fast (Ctrl+Shift+G). It’s intelligible at this speed and you can get in 90 minutes worth of screencast in only 60 minutes.
I know this is probably a subjective question, but I was wondering if you could speak to using the repository directly in the controllers. I guess I’m still thinking in the old school 3-tier design and I’m equating the repositories as the data access layer and as such I’m hesitant to interacting directly with them and am leaning to wrapping them up in services. My thoughts are logic in the services and the data access in the repositories so: Controllers->Services->Repositories. Am I overthinking it and adding an un-needed layer of complexity?
As always thanks for the awesome series and making my brain work.
(FYI my background is coming from maintaining a giant classic asp application for the last two years and I’m trying to get a foundation for the coming re-write, so if my questions are a little left field or obscure, my apologies.)
I don’t think that you are introducing an extra layer of complexity at all by doing controller –> services –> repositories.
Here’s my thoughts on this (recurring) issue:
1) BUSINESS rules don’t belong in the controllers (I think we can all agree with this); the controller is about getting data to and from the view and the model (as a sort of conduit for that transfer of data)
2) If all your controller is doing is passing an arg into the repository and taking the objs returned from the repository and sending them to the view, then I think introducing a service class to do that is somewhat overkill
3) If you start to get to the point where the controller is actually doing something else with the return value( s ) from the call to the repository, then its time to factor that out of the controller and into somehting else (call it a service, call it a business rules class, etc.)
As you are seeing in the screencasts, at this point my controllers are just sending in args and returning collections of objects to the views — and introducing services to achieve this is (IMHO) a violation if YAGNI principles. Later, as the complexity of the manipulation and logic choices of what to do with the results grows, yes, I will indeed NOT code that in the controllers but move that behavior to another class that’s outside the controllers.
I hope this makes sense and helps clarify my approach — great question, keep ’em coming~!
Steve: do you have any solution for those who unable to use Nhibernate? instead using ado.net or LINQ2SQL ?
i’m one of those who can not use NHibernate, appreicate any help.
If you are (for whatever reason) unable to use NHibernate (or any other mature, non-MS full-fledged ORM tool) then your only real choices are going to be either LINQ2SQL or (gasp!) Entity Framework. Even with the troubles that both of these technologies have when compared to just about any other mature ORM product (OSS or commercial) out there today, either LINQ2SQL or EF will get you further faster than trying to ‘roll-your-own’ ORM or just using ‘raw’ ADO.NET directly.
But both LINQ2SQL and EF have their challenges (technological and political/organizational).
LINQ2SQL is rumored to be near its end-of-lifecycle as a MS technology (e.g., much as with WinForms vs WPF, WinForms isn’t going away any time soon but neither will it get any more attention/features and the same now seems to be true of LINQ2SQL) and so basing a new app on what is essentially a sundowning technology seems a poor long-term decision.
EF has its own challenges, not the least of which are all of the technology issues (that I won’t bother to rehash here as you can find them for yourself all over the rest of the Internet) but also because there is a complete lack of non-MS-database-providers for EF at this time. Oracle, for example, had been rumored to be working on a provider for EF but has (my best info) postponed its release for an indeterminate amount of time b/c their own performance testing of the thing leads them to believe that releasing a provider for EF for Oracle will actually HURT them in the marketplace (a completely defensible marketing position and one that doens’t bode well for EF adoption since one of the points of EF was DB-agnosticism but EF as it exists today is a pure-MS play — and only SQL 2005/2008 at that, no Access, no XML data source, etc.).
I think that if you are interested in trying to be ‘agile’ and focus on some of the core principles that I (and others) espouse and you are ‘stuck’ with only the universe of MS-provided solutions then you are probably best off looking at some of the refactoring efforts for Oxite presently being undertaken by someone like Rob Conery who is attempting to steer that project away from the brink of disaster but within the limits of a MS-centric data-access technology ( http://blog.wekeroad.com/blog/oxite-refactor-take-1/ )
There exists right now a very real (unanswered) question in my mind as to whether the MS-only universe of provided software infrastructure libraries is actually capable of being the (exclusive) foundation atop which one could build a solution that remains true to some of the ALT.NET / Agile / SOLID / DDD fundamentals. Hopefully with what Rob is undertaking, we will soon see some of the answer to this question.
I’m watching to see myself, frankly.
I have been following your current series and like it. IMHO, I think you probably might be missing on logging functionality. If this is something you can consider, it would be a great asset to this series.
Logging will be coming in the app, I promise. Just later on as we layer more functionality into the system.
Thanks for the input~!
First of all I’d like to thank you for making these videos. Truly its really helpful in many ways. Thanks!
Suppose we were to add “tagging” capabilities to both Skill and Employee. What would be the best way to implement it? If Skill and Employee implements ITaggable, how would this look like in DDD? More interestingly, how would the persistence look it?
Sorry for an additional question with can not be carried to Agile 🙂 When I watched your screencasts I wondred, how quickly you work with code with Refactor Pro! and CodeRush. Please, could you tell a key combination which allows you to sort class properties with fields and put them to different regions? Or how to adjust CodeRush to achieve this goal? Thank you.
P.S. Thank you for screencasts, it’s very pleasant and exciting to watch how professional work with project 🙂 Thank you one more time 🙂
What you are seeing in the screencasts where I quickly use a keystroke to re-order all the members of my class is a tool called ‘ClassCleaner’. I blogged about it (and the other tools that you see in the screencast) in a prior post here: http://unhandled-exceptions.com/blog/index.php/2008/07/16/confessions-of-a-developer-tool-hound/
If you are running a more recent build of DXCore/RefactorPro/CodeRush, the you will be interested in these two additonal posts here: http://unhandled-exceptions.com/blog/index.php/2008/11/28/cr_classcleaner-and-cr_documentor-builds-updated-for-dxcore-322/ and here: http://unhandled-exceptions.com/blog/index.php/2008/12/29/cr_classcleaner-build-updated-for-dxcore-323/ where I provide updated binary donwloads the add-in that are are compiled against the more recent and then the current DXCore release.
Note as mentioned in those posts, you don’t need the commercial coderush or refactorPro tools to run ClassCleaner, just the freeware DXCore run-time from Dev Express.
Glad you are enjoying the screencasts — thanks for the comments and hope this helps~!
Thank you a lot! It works! 🙂
Thanks so much for the informative screencasts. I learned a great deal from them.
I was running the units tests but saw an error:
failed: The container has not been initialized! Please call IoC.Initialize(container) before using it.
System.InvalidOperationException: The container has not been initialized! Please call IoC.Initialize(container) before using it.
at Rhino.Commons.UnitOfWork.Start(IDbConnection connection, UnitOfWorkNestingOptions nestingOptions)
The error occurred in this line of all unit tests:
When I ran the portal web site, everything worked fine including the UnitOfWork.Start() in the web project. So, I guessed the problem was somewhere in the unit tests only. I was not sure why RhinoCommons was not getting the Castle container.
I google the error. Somebody mentioned that the versions of the Castle stack might not match. So, I pulled down NHibernate, Castle and RhinoCommons in the trunk and tried to build them using NAnt. But I ran into build error in NHibernate, researched for the error but had no luck so far.
Any ideas? Thanks.
I have very stupid question. HOW and WHERE you will load all existing skills for an employee? The property skills is read only. I am wondering how you will do it.
Forget the previous comment. NHibernate do it for you. I am trying to do this with datasets because the project is small.
PS: Greetings from Bulgaria!