NuTemplates

Monday, December 15, 2014

How to make solution templates with NuGet packages

Visual studio templates capabilities are quite limited. Yes, you can save some work but you basically can only do projects and files with heavy limitations. What about if we put some executable code in to the equation?

The Problem

Within our organization (NuGetting Soft), there is a typical VS Solution that developers need to create quite often. It has 3 projects:

  • Interface with all public stuff, interfaces, service parameter and return types.
  • Domain with the actual logic and all private implementation stuff.
  • Tests with all unit tests.

More than just saving people time, we want all the solutions to be arranged in a particular manner with assemblies and namespaces named accordingly to the specific domain being implemented. If some team wants to build something for Human Resources we want: NuGettingSoft.HumanResources.Interface for the interface, NuGeetingSoft.HumanResources for the domain and HumanResources.Tests for the unit tests.

NuGetting

NuGet packages are an easy and clean way to deploy libraries. I recently discover you can put some code in there as well. Powershell scripts, which are quite powerful and not hard at all to get started with.

You’d need to install NuGet and make sure it is accessible from the command line. Then go ahead and create a VS Solution with a Project and open the Package Manager Console (PM). We see something like this:

Playing with NuGet

Create a Tools\Init.ps1 file:

Param($installPath, $toolsPath, $package, $project)

Write-Host $installPath
Write-Host $toolsPath

Not very useful but I promise it will grow. This Powershell file will be executed the first time a package is installed and every time the solution is loaded afterwards. Powershell is the language we can use to program custom operations in NuGet packages.

Now we create a nuspec file:

<package>
  <metadata>
    <id>NuGetting</id>
    <version>1.0.0.0</version>
    <authors>NuGetteer</authors>
    <owners>NuGetteer</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Fiddle with Nuget scripts</description>
  </metadata>
  <files>
    <file src="Tools\**\*.*" target="Tools"/>
  </files>
</package>

Once packed, we will have a NuGet package that would only execute our Init.ps1 file. Let’s pack it and install it in our own solution. Go to the PM and execute:

NuGet pack NuGetting\NuGetting.nuspec

We get something like this:

Attempting to build package from 'NuGetting.nuspec'.
Successfully created package 'C:\Path\NuGetting.1.0.0.0.nupkg'.

We now install our newly created package:

Install-Package NuGetting -Source 'C:\Path\'

Voilà. We get the following output:

Installing 'NuGetting 1.0.0.0'.
Successfully installed 'NuGetting 1.0.0.0'.
C:\Path\NuGetting.1.0.0.0
C:\Path\NuGetting.1.0.0.0\tools

As you can see, we get the 2 lines we wrote with the Write-Host commands. We need to uninstall the package so we can continue fiddling with it until we are tired:

Uninstall-Package NuGetting

Crafting a template

Let’s create a solution that would look exactly like the one we need:

Work in progress

We put everything in there: all the projects and references between projects. Then we close the solution and start with the fun part.

First clean up: delete all compiled binaries (obj and bin), anything else your IDEs might have left around. All these are usual garbage.

Then we must edit all the files that contain information we want to be modified when applying the template.

Start with the solution file

Just at the top of the file you’d find the lines that matter:

Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = 
    "Interface", "Interface\Interface.csproj", "%Interface.ProjectId%"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = 
    "Domain", "Domain\Domain.csproj", "%Domain.ProjectId%"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = 
    "Tests", "Tests\Tests.csproj", "%Tests.ProjectId%"
EndProject

And the GlobalSection too:

%Interface.ProjectId%.Debug|Any CPU.ActiveCfg = Debug|Any CPU

We’ve replaced the project Ids with tokens (e.g: %Interface.ProjectId%). Project names and paths could be replaced too, but for simplicity we won’t. I recommend not touching the Ids on the left, no idea what they are.

Projects

Here we need to change the project Id (use guid’s curly braces format for these ones, format specifier: "b"), root namespace and assembly name:

<PropertyGroup>
  <ProjectGuid>%Interface.ProjectId%</ProjectGuid>
  <RootNamespace>NuGettingSoft.%Domain.Name%</RootNamespace>
  <AssemblyName>NuGettingSoft.%Domain.Name%.Interface</AssemblyName>
</PropertyGroup>

And the references:

    <ProjectReference Include="..\Interface\Interface.csproj">
      <Project>%Interface.ProjectId%</Project>
      <Name>Interface</Name>
    </ProjectReference>

We do the same for all other projects.

Code Files

We do the same here. In our example we just have the AssemblyInfo.cs files. Here we need to set the assembly Id (use guid’s digits format for these ones, format specifier: "d"):

[assembly: AssemblyTitle("NuGettingSoft.%Domain.Name%.Interface")]
[assembly: AssemblyProduct("NuGettingSoft.%Domain.Name%.Interface")]
[assembly: Guid("%Interface.AssemblyId")]

Template is ready!! Now we need to work on how to apply it.

The Core

Create a NuGet package with an Init.ps1 file to apply the template. Let’s walk thru the script file contents.

Define the token values

$tokens = @{
    "Domain.Name" = $domainName
    "Domain.ProjectId" = Create-ProjectId
    "Interface.ProjectId" = Create-ProjectId
    "Tests.ProjectId" = Create-ProjectId
    "Domain.AssemblyId" = Create-AssemblyId
    "Interface.AssemblyId" = Create-AssemblyId
    "Tests.AssemblyId" = Create-AssemblyId
}

These Create-ProjectId and Create-AssemblyId guys just generate a guid and format’em as I said before, either "b" or "d".

Apply all templates

To all files in the template folder, for that we need to know where the script is executing form. Remember the $toolsPath argument? Let’s grab it and use it:

Apply-All-Templates "$toolsPath\.." .

Here we’ve just asked to apply all templates and drop the results in the solution folder.

Function Apply-All-Templates($sourcePath, $destinationPath) {
    New-Item $sourcePath\Output -type Directory
    Get-ChildItem $sourcePath\Template -Recurse `
    | Where { -not $_.PSIsContainer } `
    | ForEach-Object {
        $source = $_.FullName
        $destination = $source -replace "\\Template\\", "\Output\" 
        Apply-Template $source $destination $tokens
    }
    Robocopy $sourcePath\Output $destinationPath * /S
    Remove-Item $sourcePath\Output -Recurse    
}

I seriously hope I’ve done a good job and previous code wouldn’t need much explanation. The idea is to iterate by all files and call Apply-Template on each of them dropping the result on a temporary folder. Later move that folder content into $destinationPath and clear all our footsteps.

File by file

Function Apply-Template($source, $destination, $tokens) {
    New-Item $destination -Force -Type File
    (Get-Content $source) `
    | Replace-Tokens $tokens `
    | Out-File -Encoding ASCII $destination
}

Simple, goes line by line and replaces all tokens it can find. The output is ASCII encoded because I’ve found problems in the past with default (which I am guessing it would be UTF-8).

Replace tokens

Function Replace-Tokens($tokens) {
    Process {
        $result = $_
        $match = [regex]::Match($_, "%((?:\w|\.)*)%")
        While ($match.Success) {
            Foreach($capture in $match.Captures) {
                $token = $capture.Groups[1].Value

                If ($tokens.ContainsKey($token)) {
                    $replacement = $tokens.Get_Item($token)
                    $result = $result -replace "%$token%", $replacement
                }                   
            }
            $match = $match.NextMatch()
        }
        $result
    }
}

This one works over the pipeline. It iterates all keys in $tokens, regex’em to the input and replaces them by their value if found.

Add projects to solution

After all templates have been applied we just need to add each of the projects to the solution. Since there are dependencies we need to specify the order. Now that we have only 3 projects, it can be done by hand, but perhaps an automatic process can be used if that number grows.

@("Interface", "Domain", "Tests") `
| ForEach-Object { Add-Project-To-Solution $_ }

And of course:

Function Add-Project-To-Solution($project) {
    $projectPath = Resolve-Path "$project\$project.csproj"
    $dte.Solution.AddFromFile($projectPath, $false)
}

Here we use a $dte, and object available from PM. All interactions with VS can be done thru it, even activating menu items. Read about the dte here.

Last but not least

Uninstall-Package $package.Id

Weird, right? The thing is Init.ps1 will be executed every time the solution is opened. We don’t want the templates applying everyday, potencially erasing all work done. Besides, this package provides nothing once installed. Other techniques to detect that templates have been applied could be used instead…and even allow more templating with package updates. But for now, let’s keep it simple.

Here we also used another object $package this one is a NuGet.OptimizedZipPackage, you can read more about it here. It has zillions of properties and methods. You’ll need to navigate the hierarchy or reflect compiled NuGet to get the whole list. I’ve found these to be very useful:

class OptimizedZipPackage {
  string Id { get; }
  string Title { get; }
  IEnumerable<string> Authors { get; }
  IEnumerable<string> Owners { get; }
  string Summary { get; }
  string Description { get; }
}

You can get your hands into the $project if the package would have been installed into a project. You would find info about it here.

Wrap it up

That was pretty much of the heavy artillery, there are some more helper functions out there but they are not worthy to be shown here. I’ve extracted all these functions into a library file: Template-Tools.ps1, as I’am likely to need them again. That will actually trigger a warning when NuGet packing by saying that it’s an Unrecognized PowerScript file, just pay no attention to it.

Before we NuGet pack it, all we need is a nuspec file:

<package>
  <metadata>
    <id>NuGettingSoft.SolutionTemplate</id>
    <version>1.0.0.0</version>
    <authors>NuGetteer</authors>
    <owners>NuGetteer</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>NuGettingSoft Solution Template</description>
  </metadata>
  <files>
    <file src="Template\**\*.*" target="Tempalte"/>
    <file src="Tools\**\*.*" target="Tools"/>
  </files>
</package>

Now we run:

NuGet pack NuGettingSoft.SolutionTemplate.nuspec

Move the resulting NuGettingSoft.SolutionTemplate.nupkg file into our organization’s private and secret NuGet repository. Our job here is done.

The Solution

Our new Omega team has been appointed to build the Domain for our Human Resources department. Sam, one of their developers, goes and creates an empty solution named HumanResources:

Empty solution for Human Resources

Then he runs on the PM:

Install-Package NuGettingSoft.SolutionTemplate

When the process ends, he gets:

Good to go

Love Automation…Don’t you?

Conclusions

NuGet packages give an organization a powerful scaffolding tool which could greatly improve uniformity and productivity. A little bit of imagination on top of it could take you anywhere. Tomorrow you might be generating very large shells with no sweat.

As usual, with power comes responsibility. You will be deploying executable code. Think the developer installing your package might be running VS as Administrator.

References

Win-Elastic vs Lin-Search

Thursday, December 11, 2014

How well does Elasticsearch ride on Linux? What about Windows? I've had no luck finding the answer. Now, my boss asked me exactly that as part of a an internal research. We have found oury answers for our specific scenario and we wanted to share them with you.

We wanted to evaluate the capacities of Elasticsearch to solve one of our problems. After several pitfalls and expending 20 times the original budget we finally came up with some rock solid results.

Our Data

We have structured data entries that look pretty much like:

{
    from: '2014-12-11',
    tag: 'root_level_tag_1',
    items: [
        {
            height: 100
            width: 90
            weight: 20
            prices: [ /* some prices */ ]
        }
    ]
}
We need to search for all the outter fields and all inner fields but the prices. There would be a hundred of items per entry and a dozen prices per item. We have 2 periods one with 28 days (4 weeks) of data and one with 180 days (6 months). For each day we will have 30k of root level object. We created one index per week and 15 shards routed by the tag field, there are 500 tags evenly distributed. It is a total of about 33 million documents per day.

Our Toys

Three nodes clusters were used for the tests. One working horse and two data nodes. No dedicated masters. For this we hired Amazon Web Service (AWS). We chose the biggest memory optimized instances (r3.8xlarge), that is: 32 vCPUs, 244GB RAM and 40 Gigabit Network. The client performing the test was similar. OSes were: Ubuntu Server 14.04 LTS and Microsoft Windows Server 2012 R2 Base, both 64 bit Editions. The tester was a Microsoft Windows Server 2012 R2 Base as well.

Tests

We executed random searches of three different kind of tests: one with small requests that would yield small responses, one medium and one that would return the whole 500 entries. There were no empty results search. The program executing the tests had 10 threads executing constantly for 5 minutes and recording the stats; 3 rounds with 1, 5 and 10 instances of the testing program. That yielded a total of 10, 50 and 100 simultaneous requests at any given moment. The response times went up (as expected) as more simultaneous requests got in.

Enough talk!!

We will group the results by kind (small and big, medium was not very different from small) and test, which will be the pair (OS, days). Time values will be in milliseconds. We will present the response times and the number of request per minute per unit of time the cluster was able to process in two separated sections.

Response times

The lower values are better

The small

The big

Number of requests per minute

The higher values are better

The small

The big

Conclusions

Windows performance was much worse than linux for all tests. The response times were acceptable though, but the number of requests per minutes was not. For big traffic internet applications this number is critical while a couple hundred milliseconds make no difference at all. If you plan to run an Elasticsearch cluster you should probably choose linux. It will perform much better and will be a lot cheaper. I can also share that it was awfully painfull to set up the tests environments and data in Windows, mostly because scripting remote commands in Windows is kind of hard and requires a lot of knowledge (which I don't have) of Windows administration. Linux on the other hand was pretty easy (same level of knowledge from my side) to script via ssh.

The "Y"

Monday, May 26, 2014

Software industry is peculiar in many senses
I've seen very good softwares and very bad ones. I've spent many hours looking at code: mine, other's; at work, at home; for money, for free, for fun. Unfortunately, good code does not mean good software. On the other hand, bad code hardly (although it might) produces good software. Also, softwares should be long maintained after they are created. This becomes very very hard when code isn't good.

I plan to gather my experiences and those of my friends and enemies and share code quality assurance techniques, tools and tricks with you.
I will make numbers, reproducible and falsifiable. I will use your opinions to evolve myself. No comment (unless very offensive) will be deleted. I will include documentation, sources and trusted references when available. But in the end I will give you my opinion, right or wrong I hope it will do you some good.

Go back to the basics

You wanna win? Always go back to the basics.
Dr. Richard Webber in Anatomy, Season 2, Episode 22
When in trouble companies try to adopt industry methodologies standards, managing techniques, coercive tactics. None usually work, at least not as good as expected. They always forget about the basics. A software is built of code. Code is the base.

I don't mean I don't agree with methodologies, managing techniques and specially coercive tactics. Just that I think they, alone, will not succeed. You need to strike at the root of the problem.
Many different things can be done to improve the code. Some, you might like, others you might hate, some others, might even require too much effort/cost to be feasible.

The quality of the code is a subjective concept. For me the most important feature is maintainability, which includes itself many features. The point is, a code takes a relatively short time to be written and released, then it takes a very long time being maintained.

Programming is craftsmanship, is an art.

This is an art but not everybody can appreciate it. Dr. Miguel Katrib (my greatest mentor), refering to Arts Appreciation
I made my first program 20 years ago. It was Basic on an MSX. It defined my life. Many years had to pass until I got to University and discovered most of the programming I think I knew, was wrong. Now every single day that passes I learn some of what I've done the day before was wrong. I learn much more from my failures than from my successes.

This will be a journey by misstakes and headaches not about success and enlightment.

Healthy software development cycle

for the developers
  • Your code should compile with no errors at any time. Which means every change you made will not break local build. Every minute your code does not compile you are breaking the cycle.
  • You should be able to run it often. Let's say every couple of minutes.
  • Your changes should be integrable often, let's say 2 or 3 times a day you can check in changes without breaking the CI build and download latests changes without breaking local build. The longer you wait to integrate changes greater are the chances to break something when merging.
  • You should be able to test everything let's say 2 or 3 times by release. If you only test once before a release and you find problems...then what? Delay the release?...customers and bosses will be furious! It will be better to delay one component/feature release than the whole bunch.

Quality checkpoints

There are many places to measure/improve the code quality. From the top, the user end till the bottom, the tiniest component. Each place has its features, challenges, pros and cons. I think a software cannot be quality assured only at the user end. Why? It's very hard to do: you cannot manually test everything; it's very slow, as software grows there more and more to test, there are new features that should be tested and also all existing ones should be constantly retested. We work automatizing computers, do we really think we can manually do everything they do? Do you? Well I don't. I think the human intervention should be the last barrier. Everything should be certified before reaching that point.


Embrace science not technology

I've seen a huge tendency to empower technology over science. Technology are the tools, the stick around for a relatively short time. Science stays forever. No body has ask me on an interview what an object is. Instead the wonder if I know Sql Server or MySql. I know relational DBs, sure there would be differences between me and the guy that really deeply knows the tool. What about when the tool get obsolete? it happens all the time. If you learn stone solid theory, you will learn the tools easily and get the most out of them.

Use documented and tested patterns

I love design patterns. There are tons of them these days. Trying to invent the solution to every single problem would be at best a waste of time. There are a lot of smart people which has analysed and published solutions for most of your problems. The greeks, 2 thousand years ago knew this. Do you think every architect invented the columns again and again? We, developers, constantly do. Use trusted sources: I love and write in code project, but it ain't, msdn and wikipedia either.

Standardize the code

Use code standards, naming standards, documentation standards. Setup tools to enforce them. Define them in assemblies, don't need to impose, get people's opinion. Evolve with time: C#2 standards might not be good enought for C#5.

Code analysis

Code analysis provides a way to know how bad your code is. As said before, it's not a measure that you could relate to software quality, but it helps. It is very interesting to see how it evolves in time. I plan to make some analysis with mostly open source programs from the internet and I will statistically try to relate bugs, costs and soo.

Testing

Nowadays we work with gigantic amounts of data. Huge problem domains. Components interdependencies reach from one point of the software till light years away. Testing is hard and exahusting. Event worst when maintaining. Every bug found by any stage should be tested for all the eternity.

Human testing

Humans are smart, brilliant and creative. But are slow(very) and expensive and lazy(even more). Machines do not get tired, ask Sarah Connor, are very fast, ask John. In every release cycle the whole software has to be manually tested, over and over. These tests should follow a checklist, a script. Testers should test everything that has been changed and everything the change feature connects to, which could be basically the whole software. We'll do the math some day, I promise.

Computers are much cheaper than people. If you think otherwise...this place is not for you.

Automatic testing.

There are many different ways to implement automatic tests. I will cover the ones I know and use. To start with them might seem like a waste of time. The good thing about automatic tests is once they are running they will keep running until the end of times. Regression tests will take longer and longer but we could just add more computing power.

Testing

Let's believe for a minute we build German cars. Those are the best cars in the world. Let's mentally go to one of those factories. Everything is in order, clean. There are no oil spills on the floor.  They certify everything: screws, engines and seats.

Let's see what it would feel like in our world.

Software factory

Welcome to Kode Meister GmbH

We are agile people and use some iterative methodology. Our iterations are a week long. We have 3 developers and 1 tester. The developers finish between 3 and 5 features and solve between 5 and 10 bugs per week. For each feature and bug between 5 and 10 tests are defined. The tester must execute them all before the week ends. Our numbers are:
Average Value
Feature finished per iteration 3.6
Bugs solved per iteration 7.4
Tests per feature 6.92
Tests per bug 7.03
Tests per iteration 76.9
Minutes to perform a test 2
The numbers have been randomly generated with this.

Our developers constantly break existing features and previously solved bugs so in each iteration we must execute the tests for previous iterations (regression tests). Only 10 weeks after we started, this is what we have:

At this point the tester is overwhelmed by the number of tests. With this progression we will need more testers soon. Do you honestly believe your human testers and developers can keep up with this? You might even solve unemployment issues in Europe.

What's really bad is that it will keep growing and to make it worst, we are not being that rigorous.

You could say: that cannot be done, we cannot test this much, we'll just have to be more careful when developing. Ok, if you believe that: Go ahead to the comments and troll. Nothing from what comes next will be interesting for you. But keep in mind...you won't be making German cars no more.

If you wanna be spared of the mathematics jump to the solution.

The mathematics behind.

Let f i j be the feature j in the iteration i , F i = { f i j } the set with all features of the iteration i , b i j the bug j in the iteration i , B i = { b i j } the set with all the bugs of the iteration i , t ( x ) the number of test needed for feature or bug x . For our first iteration we will have a total of s 0 tests, where:
s0 = t ( F 0 ) + t ( B 0 ) The regression tests for the iteration i will be:
r i = s i - 1 Generalizing our simple model, the total number of tests:
si = t ( F i ) + t ( B i ) + r i Using the numbers from Kode Meister GmbH we have:



To make it worst

If you think you can pay for previous. Perhaps you can afford being more rigorous as well. Before closing a feature or a bug to ensure nothing has been broken the regression tests must be executed. This means |Fi| times more that regression tests should be executed. Same goes for the bugs: |Bi|. Finally the testers must run all the tests again, that is one more time. This new formula would be:
si = t ( F i ) + t ( B i ) + ( | F i | + | B i | + 1 ) ri
Using same numbers again we have this values:
And this graph, now in a Log10 scale:
It has gone from an arithmetic progression to a geometric one. Still think you can afford it?

Automize your tests

Testing adds an additional cost to your product, a big one. But if you want quality there is nothing else that would provide as much. I believe that in the long run it even reduces costs. It is not easy, some times you'd have a lot of ideas you won't be able to take out of your head because testing gets in the way. Think of it this way: better testing in the way, than lots of broken features.

I plan to dive deeply into testing. It basically goes like this:

Integration Tests

This is where I would start. Developers would create small scenarios were they would test how components interact together. They would use actual databases, files, network connections. Some components might be mocked. This are very cost effective. Should be constantly executed but they are slow so maybe not that often. They should be executed from the CI.

End to end tests

This is the coarse grain tests. They test against the whole system like a final user would. There are tools which allow automatizing application usage. There are tools to record actions and then replay them. The downside is speed. They require the whole environment to be running. They made changes in the databases and take about a fraction of what a test user could take to perform the whole regression test list. You could try to perform them a couple of times a day.

Functional tests

Finer than previous. Developers, working together with testers would create testing scenarios (small versions of the program). Testers would create and modify test cases, which are input and expected results. This tests are fully automatic and should be faster than previous. They could be a table with input values and expected outputs. They could be run with the CI.

Boundary tests

Used to test all the boundaries of external libraries. That is all features you use. Use it as the learning process, then keep the tests. It's important to run them when upgrading to ensure nothing has been broken. Should not be executed very often.

Unit tests

My favorites. Unfortunately, they are very very expensive. Prerequisites are astonishing. In the end, they really provide very little information about the whole. They are the best support for refactoring and keep the technical debt at bay. They also provide component specification. Must be run constantly, on every single change. They must be blazing fast. Tiny tiny tiny. Only a single component should be tested at the time, all its dependencies must be mocked.

Auto Diagnostics

Sunday, May 25, 2014

First step to a cure is acknowledging the problem. Thing that cannot be done if we don't know we have a problem at all. So let's diagnostics our selves shall we.

Master - Details

At Kode Meister GmbH we created a simple application with a several master -details screens. All of our features were either. Then we had trivial bugs about mainly about drawing issues (text overflows and so), medium size ones, about wrong data processing and some very hard ones with different origins.
After 10 iterations it looked like our performance was going down. If you look first iteration then last its kind of obvious.

Data was generated with this.

Estimate the performance waste

The actual performance (p) a team generates in all iterations is constant. People performance is always about the same. If your team is growing or shrinking this number would vary. But we could take per capita instead without loosing generality.

We first need to assign each feature and bug arbitrary weights based on relative effort needed to be completed or solved. e.g: a Grid is 5, a Details is 7, a Trivial is 1, a Medium is 3 and a Big is 5.

The Math

Let's say the effort (weight) needed to complete a feature is e(f), the effort needed to solve a bug is e(b). Let f i j be the feature j in the iteration i , F i = { f i j } the set with all features of the iteration i , b i j the bug j in the iteration i , B i = { b i j } the set with all the bugs of the iteration i Then the first iteration could be expressed as:
p = e ( F 0 ) + e ( B 0 )
As time passes and it becomes more and more difficult to complete features and solve bugs we want to measure how much more difficult it is now than before. We will call it Δ p i . The general formula will be:
p = e ( F i ) + e ( B i ) + Δ p i
If we put Δ p i on a graph we will see:
Although it might look pretty bad is not the worst. It's linear. Worry when it gets a higher degree, and call for help if it becomes exponential.

What next?

Grab your ITS and start collecting data of your code in the past. You could use VCS as well if it helps. If you don't have defined iteration, take segments of equal length of time. Create as many categories as you need for your features and bugs, the assign the weights accordingly.
Sometimes it's easier if you work backwards.
Mr. Jennings in Paycheck
Look at the past. See how you've been doing, a year ago, 6 month ago, now. If you are not doing good: Hang on, well get to that.