- Posted by Justin on September 30, 2008
I am using the VSTS Database Editon to manage my schema in development as well. For deployments I am using a combination of VSTS Database Edition generate scripts, manually created data migration scripts and nant.
Steps for generating scripts for deployment:
- Create a new database with the schema from the last production release.
- Do a Schema Compare in VSTS DB Edition with the project as the source and the new database as the target. Export to the Editor so that you can get the sql script to run but don’t execute the script yet. This will create you the upgrade script.
- Do a Schema Compare in VSTS DB Edition with the new database as the source and project as the target. Export to the Editor so that you can get the sql script to run but don’t execute the script yet. This will create you the back out script.
- Scan thru the generate scripts and make any additions/changes to handle the data migration. Unfortunately it is hard to auto generate a script to manage the data side of the upgrade.
- To test the scripts, restore a copy of the production database and run the upgrade/back out scripts against it.
Nant Script used for Upgrade Deployment:
<!—List of upgrade scripts -->
<property name="releases" value="3.0.1,3.0.2,3.0.3,3.0.4,3.0.5,3.0.6,3.0.7" />
<!—Reverse list of upgrade scripts used for back out -->
<property name="releases.reverse" value="3.0.7,3.0.6,3.0.5,3.0.4,3.0.3,3.0.2,3.0.1" />
<!—Current production release. Could get from DB. Used to determine how many back out scripts to run -->
<property name="current.version" value="3.0.7" />
<!— Release package number. Used to determine when to start running the upgrade scripts.
<property name="current.release" value="3.0.8" />
<!—Loop thru the releases, run all once you either hit the current release or what is in prod original. -->
<!-- Files are name v.X.X.X.AlterScript.sql and vX.X.X.DataAlterScript.sql -->
<property name="runmorepappscripts" value="false" />
<foreach item="String" in="${releases}" delim="," property="count">
<if test="${property::get-value('count') == property::get-value(current.release')}">
<property name="runmorepappscripts" value="true" />
</if>
<if test="${property::get-value('runmorepappscripts') == 'true'}">
<property name="filename" value="${path::combine(release.database.dir, 'v' + count + '.AlterScript.sql')}" />
<if test="${file::exists(path::combine(release.database.dir, filename))}">
<echo message="Running ${filename} script against ${database.name} database on ${database.server}" />
<sql
connstring=""
transaction="true"
delimiter="GO"
delimstyle="Line"
batch="false"
print="true"
source="${path::combine(release.database.dir, filename)}"
verbose="${verbose}" />
<echo message="Completed ${filename} script against ${database.name} database on ${database.server}" />
</if>
<property name="filename" value="${path::combine(release.database.dir, 'v' + count + '.DataAlterScript.sql')}" />
<if test="${file::exists(path::combine(release.database.dir, filename))}">
<echo message="Running ${filename} script against ${database.name} database on ${database.server}" />
<sql
connstring=""
transaction="true"
delimiter="GO"
delimstyle="Line"
batch="false"
print="true"
source="${path::combine(release.database.dir, filename)}" verbose="${verbose}" />
<echo message="Completed ${filename} script against ${database.name} database on ${database.server}" />
</if>
</if>
<if test="${property::get-value('count') == property::get-value(current.version')}">
<property name="runmorepappscripts" value="true" />
</if>
</foreach>
Nant Script for backout
<!—Loop thru the releases reverse, run all until you hit what was original in prod. Files are name v.X.X.X.AlterScript.sql and vX.X.X.DataAlterScript.sql -->
<property name="runmorepappscripts" value="true" />
<foreach item="String" in="${releases.reverse}" delim="," property="count">
<if test="${property::get-value('count') == property::get-value(‘current.version')}">
<property name="runmorepappscripts" value="false" />
</if>
<if test="${property::get-value('runmorepappscripts') == 'true'}">
<property name="filename" value="${path::combine(release.database.dir, 'v' + count + '.BackoutAlterScript.sql')}" />
<if test="${file::exists(path::combine(release.database.dir, filename))}">
<echo message="Running ${filename} script against ${database.name} database on ${database.server}" />
<sql connstring="" transaction="false" delimiter="GO" delimstyle="Line" batch="false" print="true" source="${path::combine(release.database.dir, filename)}" verbose="${verbose}" />
<echo message="Completed ${filename} script against ${fuzion.database.name} database on ${fuzion.database.server}" />
</if>
<property name="filename" value="${path::combine(release.database.dir, 'v' + count + '.BackoutDataAlterScript.sql')}" />
<if test="${file::exists(path::combine(release.database.dir, filename))}">
<echo message="Running ${filename} script against ${database.name} database on ${database.server}" />
<sql connstring="" transaction="false" delimiter="GO" delimstyle="Line" batch="false" print="true" source="${path::combine(release.database.dir, filename)}" verbose="${verbose}" />
<echo message="Completed ${filename} script against ${database.name} database on ${database.server}" />
</if>
</if>
</foreach>
- Posted by Justin on September 29, 2008
Great post on lack of complaints not equaling success. I have seen lots of developers think this way only to be proven wrong later when they are struggling with user adoption.
Taken from: Lack of complaints does not equal success : How To Be A Good Product Manager: Product management tips
If you want to be a bad product manager, assume that lack of complaints means your product is successful. There are lots of customers using your product, so when you add a new feature or make a change and don’t hear complaints, that must mean that everything is working fine. If something was really unusable or broken or didn’t meet your customers’ needs, they would let you know. It’s much easier to just make a change or add something to the product and wait to hear feedback than to do a whole bunch of research and testing first — that’s just a waste of time, right?
If you want to be a good product manager, proactively seek out feedback rather than wait for complaints. Lack of complaints does not mean that you have a fantastic product — it just means that you are not getting any complaints.
Waiting for customers to complain is problematic for several reasons:
- Not all customers complain. Think about all of the products you use on a daily basis, and the problems you encounter with all of them. There may be a confusing button on your cell phone, a strange error message on your online banking site, or a slippery grip on a kitchen gadget. How many times have you taken it upon yourself to contact the organization responsible for that product? Despite the multitude of different ways to complain — from the traditional methods like contacting the company directly, to more modern methods of voicing your frustration on Twitter or a product review site — most customers do not make the effort to send this feedback directly or indirectly to the company. A product manager simply hoping to hear from customers with problems is only going to hear about a fraction of the problems from only a fraction of the customers. For every customer who vocally complains, there are likely tens or hundreds or thousands of others who are silent.
- Lack of complaints may mean lack of customers or users. While we would like to think that lack of feedback means lack of problems, it is often that lack of feedback means lack of experience on which to provide feedback. When a product manager adds a new feature to a product and does not hear any complaints about the feature, he may assume that the feature is a success and the fact that customer service has not received any complaints is because it is working smoothly. Unfortunately, it could be just as likely that no one is using the new feature, and thus no one has any experience about which to complain. If there are a small number of customers using the new feature, relying on their complaints alone may provide very skewed feedback.
- By the time someone complains, it is usually too late. While the previous two points are worth noting, this is truly the most important reason to not simply wait for complaints. For physical products, changes to a product after it is in the market can be extremely expensive and time consuming to rectify. From a purely financial standpoint, it is the responsibility of a product manager to attempt to produce the best product and thus avoid costly changes. However, even for web-based products which can be changed very quickly and cheaply, waiting for customers to complain is backwards approach to product development. Sure, it may be gratifying on the surface to say that you are able to respond quickly to problems that customers raise, but wouldn’t it be better to prevent these problems in the first place? Would you rather buy a car from a company who listens to your complaints and reacts when your car has problems, or would you rather buy a car from a company who produces a car which will not cause you problems and will not cause you to have to complain?
Ultimately, no matter how hard an organization tries to address problems and meet needs, people will complain, and product managers can benefit from listening to and understanding those complaints. However, when a legitimate complaint is lodged, rather than just reacting to it, product managers should ask, “How did we not know about this earlier?” Is the complaint related to something that the team should have known about? Would a better understanding of the customer needs have helped prevent it? Would better design or more usability testing have uncovered the underlying problem? Did a defect make its way into the final product? Did we know about the problem and just hope that no one would notice? How did it come to this — that a customer had to complain in order for us to realize something was not right?
Complaints are a valuable source of information which can be used to help improve your product, though they are only one source and should be used carefully. Product managers need to be proactive at gathering feedback from customers and prospects, though activities like usability testing, Win/Loss analysis, site visits, observational interviews, and other types of qualitative and quantitative research. Rather than just waiting for complaints and responding to them, product managers need to be focused on preventing them from occurring and getting to the root cause when they do appear.
- Posted by Justin on September 29, 2008
Good laws of continuous integration from Jeremy Miller. The first law is pretty funny but oh so true.
Taken from: Jeremy's Other Laws of Continuous Integration
1.) If you check in very often and/or first, you can make merge conflicts be someone else's problem
2.) Check in as often as you come to a stopping point. The more frequently you check in, the less troubling your merge conflicts will be. For the most part, I think you can make merge conflicts almost entirely go away after the first couple weeks of the project. We had a mild conflict today (that spawned my tongue in cheek remark about checking in first) that was caused by one pair renaming a testing utility method to make it more consistent with our other testing methods, while my pair was still using the existing method name. Both pairs knew it was coming so it was no harm, no foul
3.) Communicate with your team members anytime you think you might be doing something that would cause a merge conflict. Yet one more reason why a colocated team beats a distributed team
4.) Find ways to divide your work into smaller chunks. If you can't check in new code for days at a time because you aren't at a clean point, you may have some serious problems with your design.
5.) If you can't check in your code for a long time ( > 1/2 a day let's say), be sure to update your version of the source code with the updates from the rest of the team to make your eventual checkin easier
6.) Rotate your build notification sounds.
7.) And in the "do as I say not as I do" category, you might learn how to use a merging tool (then come teach me).
- Posted by Justin on June 27, 2008
Along with the Agile presentation, I also had the pleasure of discussing Continuous Integration. The talk centered on Cruise Control .Net and Nant. I enjoyed giving the talk and sharing but unfortunately I didn't do a great job with the demos and they didn't across the way I wanted them to. I will post some additional information over the next couple of weeks on Nant and CI. For now, the link below will get you the presentation, the sample application with all of the build scripts, 3 Nant custom task and CCNET Config file that I used for the demo.
CI.zip (390.59 KB)
Included in the ZIP File:
Demo Code
- default.build - Master build file for the solution
- common.build - All of the global properties (variables) for the scripts
- common.build - Project.build - Nant task that can be reused
- NantSchema.build - nant script to generate nant.xsd that is needed for VS intellisense
- HelloWorld.DataObject - C# Class Library
- HelloWorld.SQL - VS 2007 Team System Database Project
- HelloWorld.SSIS - Has SSIS sample build script
- HelloWorld.Tests - NUnit Test Project
- HelloWorld.Web - Web Application Project
- HelloWorld.WinForm - WinForm Project
Nant Custom Tasks
- AppSettingsWriter
- Add/Update AppSettings Nodes in App.config and Web.Config files
- Very Simple Task.
- XMLPoke should take care of what this task does
- CleanupOldBuildFiles
- Removes Files/Directories based on either a number of revisions or on a given number of days since creation.
- TaskSchedulerTasks
- Add/Updates/Removes Windows Scheduled Task
- Posted by Justin on June 27, 2008
Tonight I have the pleasure of presenting on Agile development at the SEVDNUG meeting. I focused the talk on things that I have learned over the last 4 years of using Agile. I figured that folks can read the Agile/XP books and get the Agile concept but the books don't discuss things to look out for that can trip you up or how to really convert your project to Agile from a different process. The presentation started off with a quick overview of Agile and the benefit and then jump into the learnings. I did include in the backup slides the Agile overview/concept slides since I already had them done from other presentations that I have given.
Agile.zip (464.45 KB)
The presentation is in Powerpoint 2007 format. If you don't have Office 2007, you can download the Compatibility Pack which will allow you to view/edit/save Office 2007 formatted files