Here be Books
Steve Smith tagged me with his books post last week, which was his response to Sadukie’s post on books. I will of course keep this modern chain letter going. Here be dragons books.
Currently and just finished reading: I just visited my local library and picked up a copy of Planet of Twilight, which is the third book in a Star Wars trilogy. I’ve recently finished reading the second book of the same trilogy, Darksaber. Although I don’t like the name “Darksaber,” it is a well-written, entertaining book. My wife tells me, however, that I will not find the same to be true of Planet of Twilight.
On the technical side of things I’ve just started reading Agile Principles, Patterns, and Practices in C#, which lines up very well with a lot of the techniques I use in my day-to-day development, and I will be adding it to my required reading list shortly.
I plan to be reading a little bit less right now as I have been playing StarCraft 2. Let me know if you want to play a match.
From what medium I like my books: I haven’t ever gotten any of the digital readers, but I have read PDFs on my computer and on my phone. I’ve also used some of the book reader applications for my phone, and I tend to prefer reading books on pages printed on dead trees. Perhaps it’s just that I’ve not yet tried a good enough interface for digital reading. I intend to try one eventually.
Some book recommendations: If you’re interested in reading any Star Wars novels I would recommend that you begin with either the Thrawn trilogy by Timothy Zhan: Heir to the Empire, Dark Force Rising, and The Last Command or with the Michael Stackpole’s X-wing series: Rogue Squadron, Wedge’s Gamble, The Krytos Trap, and The Bacta War.
If you’re interested in reading some fantasy stories I would recommend starting the Drizzt books starting with the first trilogy written about him, The Icewind Dale trilogy: The Crystal Shard, Streams of Silver, and The Halfling’s Gem.
For technical books, please check my not-so-up-to-date list of recommended software development books.
Tag, You're Up Next...
What are you reading?
DoD TSP BOK - Free eBook, “Team Software Process (TSP) Body of Knowledge (BOK)”)
Carnegie Mellon Software Engineering Institute - Team Software Process (TSP) Body of Knowledge (BOK)
“The Team Software Process Body of Knowledge (TSP BOK) was drafted to define the fundamental knowledge and skills that set TSP-trained individuals apart from other software professionals. It helps individual practitioners to assess and improve their own skills, provides employers with an objective baseline for assessing the process improvement skills and capabilities of their development team members, and guides academic institutions that want to incorporate TSP into their software and other engineering courses or curricula. The TSP BOK also facilitates the development of TSP certification programs that are based on a well-established standard set of knowledge and skills.” [GD: Description leached in full]
From the PDF;
“…
The ideas and findings in this report should not be construed as an official DoD position. It is published in the interest of scientific and technical information exchange.
This work is sponsored by the U.S. Department of Defense. The Software Engineering Institute is a federally funded research and development center sponsored by the U.S. Department of Defense. …” [GD: Our tax dollars at work ;]
I’m not really sure we need another software development TLA or certification program, but I also know the software development process it still very chaotic and entirely too much re-inventing of the process wheel is still going on (for a very simple example, how many businesses still make up as they go their own dev position descriptions…? like all of them?).
What struck me about this document was that it seemed that the entire team was addressed, from leadership to end-users/stakeholders. It also seemed pretty “real world” with discussion of team dynamics, administration stuff like weekly meetings, checkpoints, coaching, etc. I also liked, “…It helps individual practitioners to assess and improve their own skills…” I feel that the only person responsible for improving your skills is you, so this personal responsibility message struck a cord with me.
In short this doesn’t seem to be just blue sky/perfect world/lost in academia stuff…
Added to me “Should Read This Soon” pile.
Here’s some snips and content from the PDF;
Here’s an dump of the ToC so
Table of Contents i
List of Figures v
Acknowledgments vii
Executive Summary ix
Abstract xi
1 Introduction 1
1.1 Purpose for the TSP BOK 2
1.2 Sources and Influences 3
1.3 Document Organization 3
2 TSP BOK Structure and Terminology 5
2.1 Structure of the BOK 5
2.2 Operational Definition of Terms 5
3 The TSP Body of Knowledge 7
Competency Area 1: TSP Foundations and Fundamentals 9
Knowledge Area 1.1: Knowledge Work 9
Knowledge Area 1.2: TSP Prerequisite Knowledge 12
Knowledge Area 1.3: TSP Principles 14
Knowledge Area 1.4: TSP Process Elements and Measures 15
Knowledge Area 1.5: TSP Quality Practices 17
Competency Area 2: Team Foundations 19
Knowledge Area 2.1: Teams and Teambuilding 19
Knowledge Area 2.2: Team Types, Styles, and Dynamics 22
Knowledge Area 2.3: Team Formation and Membership 26
Knowledge Area 2.4: Team Member Responsibilities 28
Knowledge Area 2.5: Team Member Roles 29
Knowledge Area 2.6: Team Leader Role 34
Knowledge Area 2.7: Coach Role 37
Competency Area 3: Project Planning with TSP 41
Knowledge Area 3.1: Change Management Fundamentals 41
Knowledge Area 3.2: Piloting TSP in an Organization 45
Knowledge Area 3.3: Preparing Management and Teams for TSP Implementation 48
Knowledge Area 3.4: The TSP Launch Meetings 51
Knowledge Area 3.5: The TSP Relaunch 57
Competency Area 4: Project Implementation and Tracking with TSP 61
Knowledge Area 4.1: Weekly Meetings 62
Knowledge Area 4.2: Checkpoints 64
Knowledge Area 4.3: Communicating with Stakeholders 65
Knowledge Area 4.4: Replanning 67
Knowledge Area 4.5: Phase, Cycle, and Project Postmortems 70
Competency Area 5: Gathering and Using TSP Data 72
Knowledge Area 5.1: Data Recording 73
Knowledge Area 5.2: Gathering and Using Size Data 73
Knowledge Area 5.3: Gathering and Using Schedule Data 75
Knowledge Area 5.4: Gathering and Using Quality Data 75
Knowledge Area 5.5: Gathering and Analyzing Postmortem Data 79
Competency Area 6: Scaling Up the TSP 82
Knowledge Area 6.1: Organizational Implementation 82
Knowledge Area 6.2: TSP Process Variations 84
Knowledge Area 6.3: Large-scale TSP Teams 90
Appendix A: Engineering Guidelines 92
A1 Principles of Modern Engineering Work 92
Appendix B: Project Management Guidelines 94
B1 Operational Processes for Project Management 94
B2 Project Management Using TSP 94
B3 Managing TSP Plans 96
B4 Managing Team Communication 97
B5 Managing Team Project Focus 97
B6 Managing Team Roles 98
Appendix C: TSP Coaching Guidelines 104
C1 The TSP Coach Role 104
C2 Guidelines for Introducing TSP into an Organization 105
C3 Guidelines for Launching Teams 107
C4 Guidelines for Coaching Teams 109
C5 Guidelines for Coaching Role Managers 111
C6 Guidelines for Assessing Team Characteristics 112
C7 Guidelines for Coaching Plan Management Issues 114
C8 Guidelines for Coaching Data Management Issues 116
C9 Guidelines for Data Analyses 118
C10 Guidelines for Coaching the Team’s Quality Management 120
C11 Guidelines for Coaching the Team’s Schedule Tracking 120
C12 Guidelines for Coaching the Postmortem 122
C13 Guidelines for Coaching TSP Multi-teams (TSPm) 122
C14 Guidelines for Coaching Other TSP Team Types 124
Appendix D: TSP Team Leader Guidelines 126
D1 The Team Leader Role 126
D2 Team Leader Guidelines for Plan Management 127
D3 Team Leader Guidelines for Quality Management 128
D4 Developing the Team 128
D5 Protecting the Team 129
D6 Working with the TSP Coach 129
Acronyms Used 131
References 132
The Executive Summary;
“… As the character of engineering technology has changed in the post-industrial revolution, an increasing proportion of engineered products are actually components of entire systems of products that directly support end-use applications such as driving, flying, or medical diagnoses and treatments. These products and systems must meet critical performance, safety, security, survivability, and usability requirements. Not only must these modern engineering products be of the highest possible quality, but they also must meet business-critical schedule and budget constraints.
Modern engineering work requires teams for work products that are too large or too complex to be completed by a single engineer. Furthermore, the modern engineering workforce must work in close cooperation with people who have the variety of domain skills required for the system’s design and implementation. This requires a work environment in which people with vastly different skills can work together to produce quality products that meet their functional, architectural, and property requirements. The Personal Software ProcessSM (PSPSM) and Team Software ProcessSM (TSPSM) technologies provide such an environment by proving individuals and teams with a framework for creating or tailoring processes that all members can follow, for communicating in a common vocabulary, and for planning and tracking their work using a commonly accepted set of measurements and standards.
The Team Software Process Body of Knowledge (TSP BOK) was drafted to define the fundamental knowledge and skills that set TSP-trained individuals apart from other software professionals. It helps individual practitioners to assess and improve their own skills, provides employers with an objective baseline for assessing the process improvement skills and capabilities of their development team members, and guides academic institutions that want to incorporate TSP into their software and other engineering courses or curricula. The TSP BOK also facilitates the development of TSP certification programs that are based on a well-established standard set of knowledge and skills.
The TSP BOK is intended to provide a high-level comprehensive overview of the competencies that compose the essential knowledge and skills required for the competent implementation of the TSP as a team member, team leader, coach, or manager of a TSP team. This document is not meant to provide detailed descriptions or in-depth explanations of the concepts, practices, and procedures of every component in the TSP. Rather, the purpose of this document is to provide an overview of the competencies, knowledge areas, and key concepts and skills that constitute the essential knowledge, skills, and abilities of competent TSP practitioners.
…”
(via Architects Rule! - Team Software Process (TSP) Body of Knowledge (BOK))
The Art of Agile Development
A while back I started reading a copy of the Art of Agile Development, which is a great book. I was reading the book for more than one reason. I obviously wanted to learn more about how others approach agile development, but I was also looking for a book to recommend to other developers as well as to businesses.
One of the biggest troubles with agile development is the initial resistance to agile development shown by both developers as well as businesses. I am even talking about the developers and businesses who have already bought in to the idea that agile can be a good thing. People agree with the overall idea of agile, when it forces them to change their existing practices many will put up at least passive resistance.
This book is my new answer to some of that. The book is written with a good amount of details and examples that will backup the information it provides about agile development, and it does so in such a way that both development teams and those working with the teams can have a better understanding of how agile development can work.
The Art of Agile Development is loaded with information about real-world problems faced by software development teams, and how agile development worked in these situations. The book covers these examples while describing the specific steps the author recommends for performing agile software development.
I don’t follow the same practices in all cases as what the book describes. I don’t manage stories in the same way, and I don’t estimate and track the time on that work the same way. This doesn’t matter, because the book is really providing information on how agile can work and how it has worked in the past. Each team needs to find how best they can apply agile and work with them. I use a mix of Agile, Scrum, XP, and anything else that the team thinks will make us work better. As long as the process helps us deliver better software we’re all about it.
If you’re considering agile or trying to convince other people to consider agile, I would recommend reading this book and passing it along to others when you’re done reading it.
Full disclosure: I did not pay for this book. The copy of the book that I read was sent to me by the publisher.
The future of OpenRasta
You may have noticed that development on OpenRasta has slowed down quite a bit recently. It’s a double-edge sword: the codebase is stable enough for most people, which has helped adoption of the 2.0 branch quite a bit, but at the same time there are new features that I want to see implemented.
As you probably know, I’m putting most of my energy on OpenWrap until we have a fully functioning first beta release, because I want the next version of OpenRasta to be completely built on top of it. So what is the future of OpenRasta?
OpenRasta 2.0 RTM coming to a shop near you soonThe current branch on github is going to be enhanced slightly by the addition of a few fixes / features that will close the loop for a 2.0 release:
- Http header processing will special-case our friend Set-Cookie, which will solve a bunch of issues people have been reported when trying to use those evil babies.
- The diagnostics output is going to be made a bit nicer by actually showing the log on the web page itself rather than the dreaded “There was an error in a contributor”.
- I’ll pull in the fixes requested by those that want to use the binder to do constructor value injection.
- We’ll put the nice logo we’ve had and not used for so long.
That’s it. This should happen in the next week or so.
OpenRasta 3.0I’ve decided to rename 2.1 in 3.0, for the simple reason that I’m going to move stuff around quite a bit, all driven by my need for better componentisation of the codebase, most of it driven by OpenWrap. I’m not ready to discuss the feature-set yet, but August will be the big development push on the first iteration. Expect a lot of splitting of code, of re-evaluation of some features that are not as much in use as I’d like, and hopefully a lot of bug fixes in the process.
In the meantime…In the meantime, you may as well get yourself acquainted with OpenWrap, because it will be mandatory for OpenRasta 3.0.
I’d also like to thank Hadi and the codebetter guys, as our bug tracking has now moved to youtrack on codebetter.com, at http://youtrack.codebetter.com/issues/OR. Let me know what you think of the new system.
Silverlight Queues: Design
I got a question about the feasibility of porting Rhino Queues to Silverlight, but that isn’t really something that can fit in that scenario. So I set down to write the design for a Silverlight queuing system. Just to be clear, I have no intention currently to actually build this at this time (well, not unless someone is willing to pay for it or I get a project that requires it). This is merely a way to get the design problem off my head.
Why can’t we just port Rhino Queues to Silverlight?
There are two reasons, one is technical, the second relates to the different way that Silverlight applications are used. The first problem is that Rhino Queues requires a way to listen to incoming messages, but Silverlight offers no way of doing such (reasonably so, FWIW, since that would turn the Silverlight app to a server, and there are probably security issues with that).
The second problem is simply that the way most Silverlight solutions are structured, there is going to be a WAN between the Silverlight app and the server, and WAN between each client. Direct connections between the Server & Silverlight client is likely to be possible only when using HTTP, and there isn’t going to be any direct communication between different clients.
This usually looks something like this:
Rhino Queues is built on the notion of independent agents, each of them containing a full queuing stack. That model will not work for Silverlight. In Silverlight, we need to support all the usual queuing features, but each agent (Silverlight application) is no longer independent.
The Silverlight Queues model will be slightly different. We introduce a Queues server component which will hold the queues & messages internally.
On the client side, the process of sending messages is:
- Queues.Send(“server”, “Orders”, new Buy{ … });
- Message is saved to isolated storage
- A background thread send the messages from isolated storage to the Queues server.
The process of receiving messages is:
- A background thread periodically pools (an alternative is a Comet using something like WebSync) the server for new messages.
- Messages are written to isolated storage
- The Silverlight acknowledge the receipt of the messages.
There are some twists here, though.
In a Silverlight application, there are going to be several possible use cases:
- Each Silverlight application has its own “queue” in the Queues server. That allows a one-way messaging platform with point to point notification. That is likely to be common in Silverlight applications that handle business transactions.
- Topics, in addition to a queue per client, we might also want to allow subscription to topics, for example, I may be interested in getting notifications when the system settings have changed. That is something that is shared among all (or a lot) of clients. The Queues server should support this as well.
An interesting approach to make the Queues server even more stateless is to remove the process of acknowledgement and change it to “give me all messages after…”
Yes, I know that this is a very high level design, but there really isn’t much here that I can call very complex.
How much interest is there in Queuing system in Silverlight?
Nine UML’s from a Niner on Nine - Nine using UML with Visual Studio 2010 videos on Channel 9
Visual Studio Visualization and Modeling Tools – Team - Channel 9 video series: UML with VS2010
“Clint Edmonson, an Architect Evangelist at Microsoft, has posted a series of videos that show how to use the Visual Studio 2010 Ultimate visualization and modeling tools in your software development process:
- Part 1: Brainstorming a Project
- Part 2: Organizing Features Into Use Cases
- Part 3: Modeling the Business Domain
- Part 4: Capturing Business Workflows
- Part 5: Architecting an Application
- Part 6: Designing a Project's Physical Structure
- Part 7: Sketching Interactions with Sequence Diagrams
- Part 8: Revealing Responsibilities with Class Diagrams
- Part 9: Organizing and Managing Your Models” [GD: Post leached in full]
Clint Edmonson - UML with VS 2010 Part 1: Brainstorming a Project
“In this screencast, Clint Edmonson presents an overview of using a UML use case diagram to brainstorm the scope and features of an application.
If you’ve got Visual Studio Ultimate, you’ve got UML… Might as well see if you can use it to help.
(via C l e m e n s - Channel 9 video series: UML with VS2010)
Creating a "New" Gem for "Nu" - From 0 to 100 in 24 Hours
Has it really been 24 hours since I jumped on the nu project bandwagon? Sure has. Let’s take a step back first.
Where Have We Been?
For months now (or maybe it’s been years) the .NET community has been talking about some kind of third party dependency package system. The much heralded RubyGems has always been brought up as the model. It was a bold and noble idea. Being able to package up .NET third party assemblies so new projects can hit the ground running.
Rob Reynolds (aka The Fervent Coder) has a great post explaining the hoopla we go through today to try to find a site, download a tools, unzip, reference, lather, rinse, repeat on every single project we do. He goes on to explain there are too many decisions in this process, it’s fragile, hard to manage, etc. Basically being able to pull down all my dependencies that I’m going to use at the start of a project (and add new ones as I go along) by issuing a single command excites the hell out of me.
Getting Ruby with It
I’ve been a long fan of Ruby, getting into it last year as I tried to find a better way to express automated testing via BDD specifications in a natural language and always finding myself turn to Ruby as a language to help with this. Dynamic languages and duck typing is the cat’s meow and I’m glad to see splinters of the DLR getting better and better in the .NET world every day.
There’s been many attempts and even full blown packaging systems built for .NET but nothing has really picked up any traction. Then about 2 weeks ago the “nu” project was born out of the efforts of people like Roby Reynolds and Dru Sellers got down and put something together. Rather than continuing the efforts of trying to build a native .NET “gem” packager, why not just use gems?
RubyGems is a package management system that provides the ability to download a package (or library) and all it’s related dependencies through a simple command. Check out Rob’s post here on some background on Gems and how it relates to .NET.
So they created Nu (which started as ngems but quickly became Nu after the suggestion of “nubular” by Dave Laribee). “Nu” stuck because it was short and sweet (and we’re all about minimalism). It does require Ruby (version 1.8.6 or high or IronRuby) and RubyGems installed but you know, that’s a small price to pay for such a powerful back-end system. I remember I had a discussion with Scott Bellware last year or so about having to “drag in” an entire programming language just to run a tool (at the time, rake) for .NET projects. He made me see the light that it really wasn’t a bad thing (although dragging in Java is a bit of a different feeling, but that’s another post).
Diving In
After getting familiar with what was going on it was time to dive in. Seriously, it’s dead simple.
- Install Ruby. I know, you’re going to get all ansy about installing Ruby on your precious .NET development system. Get over it. Download the click-click-done installer from here and stop whining.
- Open a command prompt
- Make a new directory somewhere for your test project (md c:\projects\nutest)
- Change to that directory (cd c:\projects\nutest)
- Make sure you have the latest update to gems (gem update --system)
- Install nu (gem install nu)
- Get a copy of one of the current packages available (nu install nhibernate)
- Take a look at your project tree to see nhibernate and all it’s dependencies installed
C:.
├───.nu
└───lib
├───castle.core
│ ├───mono-26
│ ├───net-20
│ ├───net-35
│ └───sl-30
├───castle.dynamicproxy2
│ ├───net-20
│ ├───net-35
│ └───sl-30
├───log4net
├───nhibernate
│ ├───Required_Bins
│ └───Required_For_LazyLoading
│ ├───Castle
│ ├───LinFu
│ └───Spring
└───nlog
├───Mono 1.0
└───Mono 2.0
Did I mention how easy this was? No I can create my project and just add a reference to the assembly I need in my project. Want to add say NUnit and Rhino Mocks to the mix?
C:\projects\nutest>nu install nunit rhino.mocks
Found Gem
Copy From: C:/Ruby/lib/ruby/gems/1.9.1/gems/nunit-2.5.5.10112/lib
Copy To: C:/projects/nutest/lib/nunit
Found Gem
Copy From: C:/Ruby/lib/ruby/gems/1.9.1/gems/rhino.mocks-3.6.0.0/lib
Copy To: C:/projects/nutest/lib/rhino.mocks
Done. Yeah, really.
Note: If you’re behind a proxy, just set an environmental variable called HTTP_POST to your proxy server and port and Bob’s Yer Uncle.
Autofac Meets Nu
My next challenge was creating a new package. I’m a big fanboy of the IoC container Autofac and found it wasn’t created as a RubyGem yet so I thought I would spend some time before my coffee this morning to package it up and see how easy this all was. And it was. Really.
Head over to Fervent Coder and read up on Robs walkthrough to create a new gem for Nu. It’s basically what I followed (although with Autofac there are no dependencies except the binaries itself).
For Autofac, I downloaded all the releases that are current (version 2.2.4) from the download page here. Autofac comes with 4 main versions: Silverlight 3, Silverlight 4, .NET 3.5, and .NET 4.0. Note that I left out the Autofac contrib release. After taking a look at it, there were all kinds of dependencies in there and I didn’t want to overly complicate things (or my first Gem). Sorry about that.
Once I had the files I extracted them all to a single folder (using their zip names) then did two things: a) rename the folders so it didn’t include the version number and b) bring everything up into the root of that folder. Here’s the structure when I first extracted the files:
C:.
├───Autofac-2.2.4.900-NET35
│ ├───Library
│ └───License
├───Autofac-2.2.4.900-NET40
│ ├───Library
│ └───License
├───Autofac-2.2.4.900-SL3
│ ├───Library
│ └───License
└───Autofac-2.2.4.900-SL4
├───Library
└───License
And here’s the simplified structure after I renamed each folder and moved the contents of Library up to that folder:
C:.
├───NET35
├───NET40
├───SL3
└───SL4
Another note is that I ditched the License directories and contents. Each folder had the various license files for Autofac and a few depencies (like Moq, NUnit, etc.) but Autofac doesn’t actually reference any of these files. It only references itself so I just dropped the extra files. If I’m really peeving anyone off with this, please let me know and I’ll update the gem.
Now that I had all my files in place I was ready to follow Rob’s example to create the gemspec file and VERSION file. Here’s the gemspec file for autofac:
1: version = File.read(File.expand_path("../VERSION", __FILE__)).strip2:
3: Gem::Specification.new do |spec|
4: spec.platform = Gem::Platform::RUBY
5: spec.name = 'autofac'
6: spec.version = version
7: spec.files = Dir['lib/**/*'] + Dir['docs/**/*']
8: spec.summary = 'Autofac - An addictive .NET IoC container'
9: spec.description = 'Autofac is an IoC container for Microsoft .NET. It manages the dependencies between classes so that applications stay easy to change as they grow in size and complexity. This is achieved by treating regular .NET classes as components.'
10: spec.authors = ['Nicholas Blumhardt','Rinat Abdulin']
11: spec.email = 'emailme@bilsimser.com'
12: spec.homepage = 'http://code.google.com/p/autofac/'
13: spec.rubyforge_project = 'autofac'
14: end
I just grabbed the info from the website. Note that the spec.authors property should be the name of the authors of the library, not your name (unless of course you’re building a gem for your own project). I’m not sure if the spec.email should be theirs or mine but it didn’t manifest itself on the RubyGems site as such. Again, I can update the package if need be.
I did create a docs directory and dropped the Autofac.chm file (available from the site) into it. As for the VERSION file I just took a look at the properties of the assembly and noticed it was 2.2.4.900 (the website only shows it as 2.2.4) so I put that into the VERSION file.
After everything was done, you’ll need to create an account on RubyGems.org then you can build the project with the command “gem build project.gemspec”. In a minute you get a generated .gem file:
C:\projects\autofac\gems>gem build autofac.gemspec
Successfully built RubyGem
Name: autofac
Version: 2.2.4.900
File: autofac-2.2.4.900.gem
C:\projects\autofac\gems>dir
Volume in drive C is OSDisk
Volume Serial Number is B6FC-4710
Directory of C:\projects\autofac\gems
07/30/2010 09:43 AM <DIR> .
07/30/2010 09:43 AM <DIR> ..
07/30/2010 09:43 AM 1,053,184 autofac-2.2.4.900.gem
07/30/2010 07:03 AM 801 autofac.gemspec
07/30/2010 06:49 AM <DIR> docs
07/30/2010 06:51 AM <DIR> lib
07/30/2010 06:48 AM 9 VERSION
Once the .gem file was built I pushed it up to RubyGems (“gem push autofac-2.2.4.900.gem”) and it was done. I headed over to the autofac page on RubyGems.org and everything was golden. Version number correct, author names corect, etc.
One thing I did to polish it off was to click on the Edit link once your gem is produced and put in links to Source Code, Documentation, Wiki, Mailing list (autofac didn’t have one), and bug tracker. It’s just a simple step that you can’t set in the .gemspec file (or can you?) but gives people some links if they’re interested in looking for more info about the original library.
Roll Your Own
Like I said, this was easy. 24 hours ago I was looking at Nu; 12 hours ago I installed Ruby, created an account on RubyGems; 2 hours ago I downloaded Autofac, built my first gem, and uploaded it. There’s no reason why you can’t do the same.
Setting up your project is a breeze and it only takes 10 minutes at most to get it packaged and uploaded. Having to deal with dependencies automatically is a little more involved so check out Rob’s post here on dealing with that. It’s still neither rocket science or brain surgery (or rocket surgery) so anyone can do it and it helps the Nu community in these early days to get some momentum.
What are you Waiting for?
Drop by the nu-net Google group, join in the discussion, and get started using Nu!
And remember… Nice package!
Making Application Configuration Easier Using the Castle DictionaryAdapter
The false myth of encapsulating data access in the DAL
This is a question that I get routinely, both from random strangers and when I am at clients.
I would like to design a system/application using NHibernate. But I also want to so flexible that in future ,if I unplug the NHibernate and use ADO.NET Entity framework or other framework then my application should not
crash.
In short, I am completely opposed for even trying doing something like that.
It is based on flawed assumptions
A lot of the drive behind this is based on the historical drive built in the time where data access layers directly accessed a database using its own dialect, resulting in the need to create just such an encapsulation in order to support multiple databases.
The issue with this drive is that it is no longer a factor, all modern OR/Ms can handle multiple databases effectively. Moreover, modern OR/M are no longer just ways to execute some SQL and get a result back, which is how old style DAL were written. An OR/M takes on a lot more responsibilities, from things like change tracking to cache management, from ensuring optimistic concurrency to managing optimal communication with the database.
And those features matter, a lot. Not only that, but they are different between each OR/M.
It doesn’t work, and you’ll find that out too late
The main problem is that no matter how hard you try, there are going to be subtle and not so subtle differences between different OR/Ms, those changes can drastically affect how you build your application.
Here are a few examples, using NHibernate and EF.
Feature NHibernate Entity Framework Futures Yes No Batching Yes No Transaction handling Requires explicit code Implicitly handled Caching 1st & 2nd level caching 1st level caching onlyThis isn’t intended to be a NH vs. EF, and it doesn’t even pretend to be unbiased, I am simply pointing out a few examples of features that you can take advantage of which can greatly benefit you in one situation, which do not exists in another.
It has a high cost
In order to facilitate this data access encapsulation, you have to do one of two things:
- Use the lowest common denominator, preventing you from using the real benefits of the OR/M in question.
- Bleed those features through the DAL, allowing you to make use of those features, but preventing you from switching at a later time.
Either of those add complexity, reduce flexibility and creates confusion down the road. And in general, it still doesn’t work.
There are other barriers than the API
Here is an example from a real client, which insists on creating this encapsulation and hiding NHibernate inside their DAL. They run into the previously mentioned problems, where there are NHibernate features specifically designed to solve some of their problems, but which they have hard time to implement through their DAL.
Worse, from the migration perspective, most of the barrier for moving from NHibernate isn’t in the API. Their entity model make a heavy use on NHibernate’s <any/> feature, which large percentage other OR/Ms do not support. And that is merely the example that spring most forcibly to mind, there are others.
The real world doesn’t support it, even for the simplest scenarios
A while ago I tried porting the NerdDinner application to NHibernate. Just to point it out, that application have a single entity, and was designed with a nice encapsulation between the data access and the rest of the code. In order to make the port, I had to modify significant parts of the codebase. And that is about the simplest example that can be.
The role of encapsulation
Now, I know that some people would read this as an attack of encapsulation of data access, but that isn’t the case. By all mean, encapsulate to your heart’s content. But the purpose of this encapsulation is important. Trying to encapsulate to make things easier to work with, great. Trying to encapsulate so that you can switch OR/Ms? Won’t work, will be costly and painful.
So how do you move between OR/Ms?
There are reasons why some people want to move from one data access technology to the other. I was involved in several such efforts, and the approach that we used in each of those cases was porting, rather than trying to drop a new IDaataAccess implementation.
VS 2010 Web Deployment
This is the twenty-fifth in a series of blog posts I’m doing on the VS 2010 and .NET 4 release.
Today’s blog post is the first of several posts I’ll be doing that cover some of the improvements we’ve made around web deployment. I’ll provide a high-level overview of some of the key improvements. Subsequent posts will then go into more details about each feature and how best to take advantage of them.
Making Web Deployment EasierDeploying your web application to a server is something that all (successful) projects need to do. Without good tools to help you, deployment can be a cumbersome task – especially if you need to do it manually.
VS 2010 includes a bunch of improvements that make it much easier to deploy your ASP.NET web applications – and which enable you to build automated deployment procedures that make deployment easily reproducible. The deployment features support not just deploying your web content – but also support customizing your web.config file settings, deploying/updating your databases, and managing your other dependencies. You can kick-off deployments manually – or via automated scripts or as part of an automated build or continuous integration process.
Below is a high-level overview of some of the key new web deployment features in VS 2010. I’ll do subsequent posts that provide more details on how to use/customize each of them.
New “Publish Web” DialogVisual Studio 2010 includes a new “Publish Web” dialog that you can use to quickly deploy a web application to a remote server.
You can activate the dialog by right-clicking on an ASP.NET Web Project node within the solution explorer, and then select the “Publish” context menu item:
Selecting this will bring up a “Publish Web” dialog which allows you to configure publish location settings.
Configuring and Saving a Publish Profile
You only need to define your publish settings once – you can then save them as a named “Publish Profile” to enable you to quickly re-use them again later.
Above I’ve created a “ScottGu Site” profile, and configured it to deploy via FTPS (a version of FTP that uses SSL) to a remote server. To deploy over FTPS select the “FTP” node in the drop-down, and then prefix the server location you want to publish to with the “ftps://” prefix.
Note that you can either re-enter your password each time you deploy – or save the password for future uses in a secure location (just click the “Save Password” checkbox to do this.
Web Deploy
In addition to supporting FTP/FTPS, VS 2010 also supports a more powerful publish mechanism called “Web Deploy”. Web Deploy (earlier known as MSDeploy) provides a much more comprehensive publishing and deployment mechanism than FTP. It not only allows you to publish files, but also allows you to publish IIS Web Server Settings, Database Schema/Data, Database Change Scripts, Security ACLs, and much more.
Web Deploy can be used to deploy applications both to a single server, as well as to multiple servers within a web farm. Web Deploy is also now supported by many inexpensive Windows hosting providers (some as cheap as $3.50/month for an ASP.NET + SQL account). You can find great ASP.NET hosters that support Web Deploy by visiting this page: http://asp.net/find-a-hoster.
One Click Publish Toolbar
Clicking the “Publish” button within the “Publish Web” dialog will publish a web application (and optionally associated database schema/content) to a remote web server.
VS 2010 also supports a “one click” publish toolbar that you can add to your IDE to quickly publish/re-publish your project without having to load the “Publish Web” dialog:
Just select your publish profile from the toolbar drop-down and then click the publish icon to the right of it to begin deploying your application.
Web.Config TransformationsIn most real-world deployment scenarios, the web.config file you use for development is different than the one you use for production deployment. Typically you want to change environment settings like database connection-strings, making sure debug is turned off, and enabling custom errors so that end-users (and hackers) don’t see the internals of your application.
VS 2010 now makes it easy to customize/tweak/modify your web.config files as part of your publish/deployment process. Specifically, you can now easily have build-configuration specific transformation files that can customize your web.config file prior to the application being deployed:
You can maintain a separate transform file per Visual Studio build-environment. For example, you could configure your project/solution to have a “Debug”, “Staging” and “Release” build configuration – in which case VS will maintain three separate transform files for you. VS will automatically apply the appropriate one at deployment time depending on what your VS environment is set to.
I will dive deeper into how to perform web.config file transformations in a future blog post.
Database DeploymentVS 2010 allows you to optionally deploy a database, along with your web application files, when are using the “Web Deploy” option as your deployment mechanism. Databases deployed this way can include both schema and data, and can optionally also include change scripts to update existing databases.
ASP.NET Web Projects in VS 2010 have a special page within their the “project properties” settings to configure database deployments:
I will dive deeper into how to perform database deployments in future blog posts.
Web Deployment PackagesVS 2010 also supports a packaging option that enables you to package up your ASP.NET Web Application (together with its dependencies like web.config, databases, ACLs, etc) into a .zip based deployment package file that you can optionally hand-off to an IT administrator who can then easily install it either via the IIS Admin Tool or via a command-line/powershell script.
The deployment package you create can optionally expose application configuration settings that can be overridden (like directory locations, database connection-strings, etc). When using the IIS7 Admin Tool, the install wizard can prompt the administrator for each setting to be customized – enabling you to provide a clean customization experience without having to write any custom code to-do so. The settings can also obviously be passed as arguments on the command-line when using a command-line or Powershell script to deploy the application.
To create a web package within Visual Studio 2010, just right click on your ASP.NET Web Project node in the solution explorer and select the “Build Deployment Package” menu item:
This will compile your application, perform appropriate web.config transforms on it, optionally create .sql scripts for your database schema and data files, and then package them all up into a .zip deployment package file. Adjacent to the .zip file you’ll file a deployment script file that you can use to automate deployment of the package to a remote server.
I will dive deeper into how to create web deployment packages in future blog posts.
Continuous Integration with Team BuildMost of the VS 2010 web deployment features that I described above are built on top of MSBuild tasks & targets. The “Team Build” feature of TFS also uses MSBuild, and supports running nightly builds, rolling builds, and enabling continuous integration. This means that you can create deployment packages, or automatically publish your web applications from a Team Build environment.
I will dive deeper into how to enable this in future blog posts.
SummaryToday’s blog post covered some of the new VS 2010 web deployment features at a high-level. All of the above features Iwork with both VS 2010 as well as the free Visual Web Developer 2010 Express Edition.
Hopefully today’s post provided a broad outline of all the new deployment capabilities, and helped set context as to how they are useful. In future posts I’ll go deeper and walkthrough the specifics of how to really take full advantage of them.
Hope this helps,
Scott
P.S. In addition to blogging, I am also now using Twitter for quick updates and to share links. Follow me at: twitter.com/scottgu
How to install Visual Studio 2010 Search References and Pro Power Tools side by side
The new Visual Studio 2010 Pro Power Tools bring a new Add Reference dialog that completely replaces the classic one when you click the familiar Add Reference command:
It seems like a nice dialog that is more aligned with the new Add New dialog and the Extension Manager one. But for this particular case, I believe it's awfully overkill (what's the use of that right sidebar? what's the use for the categories of assemblies split between Framework and Extensions?).
The (also new) Search References extension which I blogged about earlier, gives you the familiar classic dialog enhanced with the must-have Search capability:
![image[10]](http://www.clariusconsulting.net/images/blogs/kzu/d5a5f81701d1_9BFA/image10.png)
This dialog has a few key usability features that make it a snap to use (and better than the Pro Power Tools one, I think): it will open up focused on the search textbox, it will remember your last search, and it supports keyboard-only usage extensively (i.e., type "entity", down-arrow to enter the filtered list, shift or control multi-select, press Enter and done!). Also, as you're already used to, double clicking on a reference also directly adds it and dismisses the dialog (in the Pro Power Tools you need to close the dialog explicitly).
If you want to continue using this familiar, lightweight and simpler dialog, but still want to install the Pro Power Tools, you can easily disable its "Add Reference" dialog by going to your %LocalAppData%\Microsoft\VisualStudio\10.0\Extensions\Microsoft\Visual Studio 2010 Pro Power Tools folder, and deleting the AddReference.dll and AddReference.pkgdef files.
Enjoy!
Add References with Search
If you have been using VS2010 for any significant amount of time, you surely came across the awkward, slow and hard to use Add Reference dialog. Despite some (apparent) improvements over the VS2008 behavior, in its current form it's even LESS usable than before. A brief non-exhaustive summary of the typical grief with this dialog is:
- Scrolling a list of *hundreds* of entries? (300+ typically)
- No partial matching when typing: yes, you can type in the list to get to the desired entry, but the matching is performed in an exact manner, from the beginning of the assembly name. So, to get to the (say) "Microsoft.VisualStudio.Settings" assembly, you actually have to type the first two segments in their entirety before starting to type "Settings".
- Lazy loading with no progress indicator: loading is done asynchronously in VS2010, supposedly improving the situation from VS2008 where it would just freeze until it was done. Well, without an indicator, you don't know when loading is done and when it's safe to assume a given assembly isn't there because it is truly not available.
- Random order while lazy loading: moreover, while the lazy loading is happening (and you don't know when it's done), entries in the list are added in an almost random order, so any scrolling or typing you do results in constant repositioning of the current selection and changes to the underlying list. This makes it effectively impossible to use the dialog until the lazy loading is completed.
- No sorting while lazy loading: related to the previous one, you cannot sort the list at all until the lazy loading is complete, so scrolling is impossible.
So we decided to do something about it. I introduce you to the Search References extension:
From the Extension Manager in Visual Studio 2010, you can simply search the Online Gallery for "Search Reference" and install it right-away:
The dialog loads VERY fast. And because a picture speaks a thousand words, here are more screenshots to get you excited.
Partial matching:
Multi-selection:
Current project .NET profile aware. Silverlight 4:
![image[23] image[23]](http://www.clariusconsulting.net/images/blogs/kzu/d5a5f81701d1_9BFA/image23.png)
Silverlight 3:
Enjoy, and don't forget to rate it!
MEF, IServiceProvider and Testing Visual Studio Extensions
In the latest and greatest version of Visual Studio, MEF plays a critical role, one that makes extending VS much more fun than it ever was.
So typically, you just [Export] something, and then someone [Import]s it and that's it. MEF in all its glory kicks in and gets all your dependencies satisfied.
Cool, you say, so let's now import ITextTemplating and have some T4-based codegen going! Ah, if only it was that easy. Turns out by default, none of the VS built-in services are exposed to MEF, apparently because there wasn't enough time to analyze the lifetime, initialization, dependencies, etc. for each one before launch, which makes perfect sense. You don't want to blindly export everything now just in case. There's also the whole VS package initialization thing which in this version of VS is not so transparently integrated with the MEF publishing side (i.e. a MEF export from a package can get instantiated before its owning package, and in fact, the package can remain unloaded forever and the export will continue to be visible to anyone).
So, you just have to calm down, and re-encounter "good"-old IServiceProvider. Turns out, that's still the "blessed" way to get your dependencies, but now you can get the service provider from MEF instead:
[ImportingConstructor] public TextTemplate([Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider)
Note that in typical VS fashion, the actual exported contract (interface) is SVsServiceProvider, which can be converted automatically to an IServiceProvider.
But, if you make your entire class just work off of this service locator (doing GetService here and there), you lose all the "explicit-ness" that comes from having a proper constructor that declares that this class needs, say, an ITextTemplating. This makes it much harder for consumers attempting to reuse the implementation to figure out what this component needs.
Fortunately, MEF does not require your importing constructors to be public, so you can provide the MEF-exclusive constructor as internal, and make the constructor with your explicit dependencies public:
[ImportingConstructor]
private TextTemplate([Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider)
: this(serviceProvider.GetService<STextTemplating, ITextTemplating>())
{
}
public TextTemplate(ITextTemplating templating)
{
Guard.NotNull(() => templating, templating);
this.templating = templating;
}
Your tests will also instantiate this class exclusively from the non-MEF constructor, and pass moqs as needed. (note I'm using a simple generic GetService extension method on IServiceProvider to make code more concise).
/kzu
A really simple ViewModel base class with strongly-typed INotifyPropertyChanged
I have already written about other alternative ways of implementing INotifyPropertyChanged, as well as augment your view models with a bit of automatic code generation for the same purpose. But for some co-workers, either one seemed a bit too much :o).
So, back on the drawing board, we came up with the following view model authoring experience:
public class MyViewModel : ViewModel, IExplicitInterface
{
private int value;
public int Value
{
get { return value; }
set { this.value = value; RaiseChanged(() => this.Value); }
}
double IExplicitInterface.DoubleValue
{
get { return value; }
set { this.value = (int)value; RaiseChanged(() => ((IExplicitInterface)this).DoubleValue); }
}
}
You can see how raising property changed on a property is just a matter of passing an expression like "this.PropertyName" to the base RaiseChanged method. This is 100% refactoring friendly. No magic strings.
Also, we support raising a property changed for an interface that you implemented explicitly, like the second case.
The base class defines the RaiseChanged method as follows:
protected void RaiseChanged<TProperty>(Expression<Func<TProperty>> propertyExpresion)
Note how the TProperty type parameter can be completely omitted from the call to RaiseChanged() from the derived class, letting the compiler figure it out. The expression, being anything matching a Func<T>, could conceivable be an invalid reference to a property the object does not own, so we validate that in the method body by inspecting the expression tree:
protected void RaiseChanged<TProperty>(Expression<Func<TProperty>> propertyExpresion)
{
var property = propertyExpresion.Body as MemberExpression;
if (property == null || !(property.Member is PropertyInfo) ||
!IsPropertyOfThis(property))
{
throw new ArgumentException(string.Format(
CultureInfo.CurrentCulture,
"Expression must be of the form 'this.PropertyName'. Invalid expression '{0}'.",
propertyExpresion), "propertyBLOCKED EXPRESSION;
}
this.OnPropertyChanged(property.Member.Name);
}
We first ensure the expression references a member and that the member is actually a property. Next, the IsPropertyOfThis method verifies that the target of that property access is actually a reference to "this". This is kinda cool:
private bool IsPropertyOfThis(MemberExpression property)
{
var constant = RemoveCast(property.Expression) as ConstantExpression;
return constant != null && constant.Value == this;
}
We just look for a constant expression and compare its value to "this" :). For the explicitly implemented property case, there will be a cast before the reference to "this", so we remove it if necessary to get access to the constant:
private Expression RemoveCast(Expression expression)
{
if (expression.NodeType == ExpressionType.Convert ||
expression.NodeType == ExpressionType.ConvertChecked)
return ((UnaryExpression)expression).Operand;
return expression;
}
All in all, a fairly simple base class with a tiny bit of strong-typed help for raising notify property changed events for view models.
Next, we'll augment it with knowledge of IDataErrorInfo and System.ComponentModel.DataAnnotations attributes.
Full ViewModel class code available.
Enjoy!
Crazy Linq: performing System.ComponentModel.DataAnnotations validation in a single statement
public static IEnumerable<ValidationResult> Validate(object component)
{
return from descriptor in TypeDescriptor.GetProperties(component).Cast<PropertyDescriptor>()
from validation in descriptor.Attributes.OfType<System.ComponentModel.DataAnnotations.ValidationAttribute>()
where !validation.IsValid(descriptor.GetValue(component))
select new ValidationResult(
validation.ErrorMessage ?? string.Format(CultureInfo.CurrentUICulture, "{0} validation failed.", validation.GetType().Name),
new[] { descriptor.Name });
}
Enjoy!
How to merge your referenced assemblies into the output assembly for improved usability
Something we've been doing in moq since the very beginning is to have a single assembly as output: Moq.dll. This reduces the clutter for users and lets them focus on what they need from our library, rather than getting the noise of whatever third-party (or internal) libraries we use to implement it.
This is good from the deployment point of view too, and if all your libraries are actually internal infrastructure assemblies, you can even make them all internal types of your output assembly.
The key to all this is ILMerge, and it's very easy to setup in a project. You just need to download the installer, copy the included executable somewhere (i.e. "Tools") near your project and reference it from a post-build task in the project. The following configuration merges all referenced assemblies that have "Copy Local" set to true into the output assembly, and internalizes all the types in those libraries (makes them all internal to the output assembly), except for those in the optional (can be empty) exclude file (which can contain a full type name per line, to leave their visibility untouched):
<target name="AfterBuild" condition=" '$(Configuration)' == 'Release' ">
<createitem include="@(ReferenceCopyLocalPaths)" condition="'%(Extension)'=='.dll'">
<output itemname="AssembliesToMerge" taskparameter="Include" />
</createitem>
<exec command=""$(MSBuildProjectPath)..\..\..\..\Tools\ILMerge.exe" /internalize:"$(MSBuildProjectPath)ilmerge.exclude" /ndebug /keyfile:$(AssemblyOriginatorKeyFile) /out:@(MainAssembly) /targetplatform:v4,$(MSBuildToolsPath) "@(IntermediateAssembly)" @(AssembliesToMerge->'"%(FullPath)"', ' ')" />
<delete files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
</target>
After merging the assemblies (only for release builds, in this case), it will delete the embedded assemblies.
Enjoy!
Update: turns out I had blogged about this before more extensively :).
Simplified INotifyPropertyChanged Implementation with WeakReference Support and Typed Property Access API
I've grown a bit tired of implementing INotifyPropertyChanged. I've tried ways to improve it before (like this "ViewModel" custom tool which even generates strong-typed event accessors).
But my fellow Clarius teammate Mariano thought it was overkill and didn't like that tool much. He mentioned an alternative approach also, which I didn't like too much because it relied on the consumer changing his typical interaction with the object events, but also because it has a substantial design flaw that causes handlers not to be called at all after a garbage collection happens. A very simple unit test will showcase this bug.
I also looked at the new WeakEvent Patterns page in MSDN but it's even worse in terms of implementing and exposing it to consumers.
So, with my ever growing love for lambdas and my strong-typed reflection approach (used by the first alternative too, btw), I thought I could do better :). Here's the result of that, which I think improves all the above choices.
Why you need weak reference supportThe importance of this cannot be understated. A delegate that you pass around has a strong reference to the instance that exposes it. This is the Target property on the delegate class. What this means is that even if the subscribing object goes out of scope and is ready to be collected, it will not be as long as the event source (the object exposing the PropertyChanged event, for example) holds a reference to it. And as long as the event subscription is there, the reference will be there too. That's why it is typically important to remove your reference once you're ready to "go" (i.e. on Dispose, you detach from the events you're listening). Needless to say, this is a repetitive, error-prone activity.
Another typical side-effect of this is that you cannot use anonymous delegates or lambdas if you need to unsubscribe, as you need to keep a reference to the originally subscribed lamdba in order to unsubscribe:
var target = new Foo(); target.PropertyChanged += (sender, args) => Console.WriteLine(args.PropertyName); // How do you unsubscribe now?? // This clearly doesn't work because even if the actual source is the same, // the delegate is still a brand-new one. target.PropertyChanged -= (sender, args) => Console.WriteLine(args.PropertyName); // So you need to keep the lambda around: PropertyChangedEventHandler handler = (sender, args) => Console.WriteLine(args.PropertyName); // Just so you can use that to subscribe/unsubscribe: target.PropertyChanged += handler; target.PropertyChanged -= handler; // So typically you're better off just adding a full instance method on your // consumer just so you have a clear pointer for unsubscribing: target.PropertyChanged += OnTargetPropertyChanged; // But now if you need contextual state in the event handler that exists // at subscription time, you need to promote that state to class fields // so that you can use that in the event handler this.someState = currentMethodState; // This is looking like .NET 1.0 already ;)The PropertyChangeManager way
I therefore decided to take a TDD approach to the issue with the following requirements:
- The programming model for consumers must not involve creating any new objects. They already have the object that will be raising property change events.
- The "old style" way of attaching to property changed events must still work, but add the weak reference support that's so badly needed. And this must be transparent to consumers.
- A new style should involve using lambdas to avoid property names as strings
- The new style should be trivial to implement for an author exposing INotifyPropertyChanged.
So I came up with these BDD-style test specifications:
- WhenSubscriberIsAlive_ThenNotifiesSubscriber
- WhenSubscriberIsNotAlive_ThenDoesNotNotifySubscriber
- WhenAddingPropertyChangedHandler_ThenNotifiesSubscriber
- WhenAddedPropertyChangedHandlerTargetIsNotAlive_ThenDoesNotNotify
- WhenRemovingPropertyChangedHandler_ThenDoesNotNotifySubscriberAnymore
These should cover all use cases.
Consuming PropertyChangeManager-enabled objectsThe fact that a given object is internally (remember requirement 1.) using this PropertyChangeManager is completely hidden from the consumer:
var source = new Foo();
source.SubscribeChanged(
x => x.Name,
foo => Console.WriteLine(foo.Name));
The first argument specifies which property you're interested in, and the second is an Action in this case for the callback when the property changes. It can of course point to a class method:
source.SubscribeChanged(
x => x.Name,
this.OnRenamed);
Optionally, if unsubscribing from the event will be needed at some point, you can just keep a reference to the returned IDisposable object from the call to SubscribeChanged:
// this could be assigned to a field, for example.
IDisposable onRenameSubscription = source.SubscribeChanged(
x => x.Name,
foo => Console.WriteLine(foo.Name));
// at some later point (i.e. IDisposable.Dispose implementation of the consumer)
onRenameSubscription.Dispose();
// now the subscription is removed, even if I didn't keep the lambda around!
The source object can still implement INotifyPropertyChanged, but you may want to do so explicitly just for its support for databinding infrastructure. The consumer would still be able to cast the object to INotifyPropertyChanged if he wanted to use the "unsafe" property name strings ;). The implementation can still be made public, though.
Implementing INotifyPropertyChanged with PropertyChangeManagerThe implementer defines a private field to hold a reference the manager:
public class Foo : INotifyPropertyChanged
{
private PropertyChangeManager propertyChanges;
private string name;
private int value;
public Foo()
{
this.propertyChanges = new PropertyChangeManager(this);
}
Note that the manager is generic and receives the type of the "change event source", in this case Foo.
Next, your properties need to be turned into "old-style" .NET properties with a backing field, because you need to add a call to the manager in the property setter:
public string Name
{
get { return name; }
set { name = value; this.propertyChanges.NotifyChanged(x => x.Name); }
}
Note that the call to the manager also leverages lambdas to avoid using strings.
In order to provide a custom implementation of the INotifyPropertyChanged.PropertyChanged event, you need to implement the interface explicitly and pass-through the implementation to the manager:
public PropertyChangedEventHandler PropertyChanged
{
add { this.propertyChanges.AddHandler(value); }
remove { this.propertyChanges.RemoveHandler(value); }
}
This is a restriction in the language, which prevents this event from being public. But it's not as bad as it sounds, as you want to encourage adoption of safer lambda-version subscription, which is the last bit to implement:
public IDisposable SubscribeChanged(Expression> propertyExpression, Action callbackAction)
{
return this.propertyChanges.SubscribeChanged(propertyExpression, callbackAction);
}
How PropertyChangeManager works
The manager works by dismembering the received delegates into their actual target and method info, to be able to weakly reference the former, while remaining able to call the latter. It's a plain list internally, which is scavenged every time an action is performed in the manager (this could be optimized somehow to only happen on Notify, but it simplified the implementation a bit, and it's not like property change performance is a big issue in UIs anyway).
Here's the full source.
Some tooling such as a custom tool, item template, or code snippets would be nice, I'll try to provide those in the future.
Enjoy!
How to set the startup program for debugging a project for the entire team
You surely have set the startup application for a project countless times:
But that setting goes your user options file, the rest of the team doesn't get to reuse the setting. And what if you repave your machine or start working on a new virtual machine and just got the sources from source control? You have to re-set this value again and again.
Turns out that this setting goes to a file named after your project file plus the ".user" extension. This file is just a fragment of an MSBuild file, and would look something like:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<StartAction>Program</StartAction>
<StartProgram>C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe</StartProgram>
<StartArguments>/rootSuffix Exp</StartArguments>
</PropertyGroup>
</Project>
And because this just plain MSBuild properties, you can copy the entire PropertyGroup to your main project file, delete this .user, and check-in your change. From now on, everyone on the team will have this setting enabled, and you will have it too if you get a clean environment eventually :)
How to install Reactive Extensions for .NET 4.0 Beta 2 on VS2010 RC
- Get the .NET 4.0 Beta 2 download from MSDN.
- Open the downloaded .exe with 7zip (i.e. right-click on file, select 7-Zip > Open Archive)
- Navigate to the .rsrc\RCDATA\ "folder" and open the CABINET file:
- Extract the contained MSI, install and enjoy!
I thought I'd need to crack the MSI open with the good old Orca tool, but turns out I didn't have to!
Stay tuned, my Reactive Framework Extensions Generator will be soon updated to RC too :)
Enjoy!
How to quickly setup the best free Diff/Merge tool with VS 2010
First go get the tool. It's free and it rocks.
Next, save this XML to a file with a .vssettings extension:
<UserSettings>
<ApplicationIdentity version="10.0"/>
<Category name="Source Control_TeamFoundation" Category="{2A718788-A6D9-44C5-90EF-438BF5B06A74}" Package="{4CA58AB2-18FA-4F8D-95D4-32DDF27D184C}" RegisteredName="Source Control_TeamFoundation" PackageName="Microsoft.VisualStudio.TeamFoundation.VersionControl.HatPackage, Microsoft.VisualStudio.TeamFoundation.VersionControl, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<PropertyValue name="UserTool1" extension=".*" operation="Compare" command="C:\Program Files (x86)\SourceGear\DiffMerge\DiffMerge.exe" arguments="/title1=%6 /title2=%7 %1 %2"/>
<PropertyValue name="UserTool2" extension=".*" operation="Merge" command="C:\Program Files (x86)\SourceGear\DiffMerge\DiffMerge.exe" arguments="/title1=%6 /title2=%8 /title3=%7 /result=%4 %1 %3 %2"/>
</Category>
</UserSettings>
Finally, go to Tools > Import and Export Settings in VS and import that file by clicking Browse on the third and final page.
What this does is set the great SourceGear DiffMerge tool as the diff and merge tool to use for all your files. I find it much more usable and smart than the built-in TFS one.
For the ultimate collection of settings for diff/merge tools in VS, see James' blog post.
Enjoy.
