Sunday, September 12, 2010

TEAM.Commons: Introduction

This is the 1st of several posts about TEAM.Common, a set of functionality I use in every project and that I'd like to share.
  1. Querying.
  2. Formatting objects into readable strings.
  3. Threading - part 1 (introduction)
  4. Threading - part 2 (parallelization)
  5. Messaging (in-process and inter-process)

For some time I've been trying to organize, stabilize and share some common code I use in all my projects and that I find myself copying over and over.

This code matures with me and it will be nice to keep some part of my evolution as a developer in this code's history.

Last time I published what I called Romialyo SDK. Since then I have already made some improvements and stopped using git in favor of Mercurial, so here is the new TEAM.Commons.

I'll try to blog about it because I feel there are many things in there that could be used by many people and more importantly, I'd love to get some feedback on this code because it contains what I feel are the best things I've coded.

Any improvement on this code will be a direct improvement on my abilities.

Remember, you can get all this code for free at bitbucket: http://bitbucket.org/rodolfograve/team.commons/overview

Check it out to get ideas, or simply use it as it is. It's working out for me and my team.

Saturday, July 17, 2010

Another award for TEAM's TimeTracker

This has happened many times in the last few months, but every time is important:

TEAM's TimeTracker has been awarded the "Famous Software Award" by "Download.FamousWhy.com":
TEAM's TimeTracker

These later awards have inspired me to spend some time on my old applications trying to make them better, and I have recently released version 2.4.0 of TEAM's TimeTracker and version 0.2.0 of TEAM's Db4o Management Studio.

I'd like to ask everyone who is using or have used these application to leave their comments and suggestions at bitbucket.org:

Tuesday, June 29, 2010

I'm a db4o MVP

db4oMVP2010

Well, this came as a great surprise to me. Today I received an email from db4o.com explaining I had been selected as db4o MVP thanks to my TEAM's db4o Management Studio application. (Blog post here. Download from here.

I'm the 11th in the list of MVPs: dVPDirectory2010

I've been using db4o for a while. About a year ago I created the db4o Management Studio because I found no suitable tool to inspect a db4o database. This is an issue when you don't have the definition of the classes you have stored in that database, or even when you just don't want to spend time writing an application to inspect the database.

Finally, here is an extract from the email:

Let me be the first to congratulate you! You have been selected as a db4o Most Valued Professional (dVP) awardee for the year 2010.
The dVP is our community program first launched at the db4o User Conference (dUC) in July 2006 in London. The purpose of the initiative is to honor individuals like yourself who have shown a large commitment towards the db4o Community - by providing valuable peer support in the forums or outstanding contributions to the db4o software ecosystem (such as db4o related projects, articles, books, translations, etc) or by consistently spreading the word about the db4o technology (through blogs, webcasts, etc). The status is awarded for a given year (in this case 2010) and has to be re-earned every year.

Nice :-)

Friday, June 11, 2010

Handling configuration in Enterprise environments

Have you ever faced the problem of handling a complicated configuration in an Enterprise environment where there are dozens of components interacting (databases, web services, FTP sites, queues, etc)?

Mix this with automated deployment and some deployment environments (integration, QA, staging, production) and you have a complex problem to solve. A wrong solution could undermine your whole architecture, making deployment chaotic and untestable.

We've faced this situation and we've come up with what I believe is a nice solution. Let's state our requirements, which is always a good exercise when solving a problem:

R1- Automatic deployment
We need our solution not to interfere with automatic deployment.

To me, this means to keep code and configuration separated. I don't want a super-complex deployment script which must handle deployment in every environment. I also don't want to include all my environment's passwords in this deployment script.

R2- Ease of use and maintenance for system administrators
Our solution must be easy to use and maintain for system administrators. It must be very easy for administrators to create and maintain configuration for each environment and to track changes done to the configuration.

R3- Robustness
I want all the applications to share the same configuration, specially in our environment, where several applications interact with the same databases/web services/etc. It must be impossible for application A to point to a database Db_staging while application B points to Db_integration. They must always point to the same database.

R4- Flexibility
At least in our case, the staging/QA/integration environments are far from being identical to our production environment, mainly due to infrastructure expenses: we have 10+ servers in production and we only have 2 servers per environment. We can not afford to have 10+ servers per environment.

Besides, you never know what a developer will need in order to test the application in their boxes.

So, our solution must allow a great deal of flexibility, assuming nothing about the different environments.

R5- Ease of use for developers
It must be very easy for developers to get the configuration values and to tamper with them in their development environments.

R6- Security
Finally, for us, it was very important to have one single database user per application. But this could be a very particular requirement.

The (simplified) solution
S1- Global configuration file: create a file (or files) that contain all your configuration resources (connection strings to databases, ftp connection details, urls to web services, etc).

We choose an XML file with key/values:

<add name="MyDB1" value="Data Source=stagingSQL;Initial Catalog=MyDB;User ID=user;Password=pass"/>

S2- Create a copy of this file per environment, and put it under version control so that you can check for modifications.

S3- Create a project in your CI server that deploys this configuration file(s) to the right servers when a change is detected.

So far we have handled requirements:
R1- We have automatic deployment of the configuration because it is a simple plain-text file under version control that is automatically deployed by our CI server (or any other mechanism you prefer).

R2- System administrators only have to commit changes to the configuration files in the right branch in order to modify an envinroment's configuration.

R3- There isn't a configuration file per application but a single "source of truth": the global.config file. There is no way you can get two different values for the same key.

R4- There are no limits to what you can place in a text file. The only requirement is that the keys are the same for all the files, otherwise the applications won't find the resources they are asking for. That should be flexible enough and some naming conventions can make it simple.

R5- Build an API to access the configuration values. Make it very transparent to users. Our client calls look like this: Environment.Current.GetDbConnectionString("MyKey"), which is very similar to AppSettings.ConnectionStrings["MyKey"].

R6- Using a very simple template for the values you can make your API to automatically handle this kind of security:

  • Have a users.config file where you have ApplicationIds -> User/Password.
  • Make your API request the running application to provide its ApplicationId before the application can access any configuration values: Environment.Initialize("MyAppId"); Any call to Environment.Current should fail if no ApplicationId has been provided.
  • Make your connection strings look like this:
    <add name="MyDB1" value="Data Source=stagingSQL;Initial Catalog=MyDB;User ID={user};Password={password}"/>
  • Finally, make your GetDbConnectionString load the ConnectionString, the ApplicationId -> User/Password values, and replace the placeholders with the actual values.
We have found this approach to be a very nice solution. Hope it helps you find your own, or you can use this one as it is.

Friday, September 25, 2009

My best WPF magic for Model-View-ViewModel (M-V-VM) with Routed Commands

Some time ago I had the required free time to think about a nice way to implement a set of classes and ideas that will allow me to build a WPF application that:

- Honors the Model-View-ViewModel pattern.
- Keeps the view as simple as possible, ideally as a template and no code-behind.
- Uses the power of the Command pattern in WPF (Routed Commands), keeping the View agnostic about the logic encapsulated in commands.

After some attempts, the result are 2 classes that make this all possible in a very elegant way, I think. The first class is the ViewModelBase (fragment):

public abstract class ViewModelBase
{
  // Something like the "Null object pattern"
  protected static ViewModelBase EmptyViewModel = new EmptyViewModel();

  public IEnumerable CommandBindings { get; }
  public IEnumerable InputBindings { get; }
  protected abstract void PrepareBindings();
}

The ViewModelBase class, as its name implies, is supposed to be the base class of all the ViewModels, and it is here where you define what to do when a RoutedCommand is executed. It is the glue between the RoutedCommands in the View and the command execution logic in the ViewModel.

Then, there is the ViewModelControl class (full text):

public class ViewModelControl : ContentControl
{
  protected override void OnContentChanged(object oldContent, object newContent)
  {
    CommandBindings.Clear();
    ViewModelBase viewModel = newContent as ViewModelBase;
    if (viewModel != null)
    {
      foreach (var binding in viewModel.CommandBindings)
      {
        CommandBindings.Add(binding);
      }
      InputBindings.Clear();
      foreach (var binding in viewModel.InputBindings)
      {
        InputBindings.Add(binding);
      }
    }
    base.OnContentChanged(oldContent, newContent);
  }
}

This control takes care of associating the CommandBindings to the visual elements so that the RoutedCommands mechanism works.

And that's it. There are some implementation details missing, but with these classes in place you just have to:

1- Create your ViewModel classes inheriting from ViewModelBase.
2- Provide the implementation of their PrepareBindings methods.
3- Create the templates for your ViewModels.
4- Bind your controls to the commands.

Using this implementation you'll get these results:

1- You'll have your RoutedCommands.
2- Logic for these commands will be in your ViewModel classes, where you can test it.
3- No event handlers, no code-behinds required.

Mix this with INotifyPropertyChanged in your ViewModels and DataModels and you'll have a cool architecture for your View. Here's an example:

1. Define a routed commands:

public class ViewCommands
{
  public static RoutedCommand MyRoutedCommand;
  static ViewCommands()
  {
    MyRoutedCommand = new RoutedCommand("MyRouted", typeof(ViewCommands));
  }
}


2. Define a ViewModel:

public class MyViewModel : ViewModelBase
{
  protected override void PrepareBindings()
  {
    this.AddCommandBindings(new CommandBinding(
    ViewCommands. MyRoutedCommand,
      (x, y) => DoSomethingIfMyRoutedIsExecutedOnThisViewModel(),
      (x, y) => y.CanExecute = CanMyRoutedCommandBeExecuted));
  }
}


3. Finally define a view with a ViewModelControl and some templates for your ViewModels and DataModels:

<Window
xmlns:baseViews="clr-namespace:Namespace.Of.ViewModelControl"
xmlns:models="clr-namespace:Namespace.Of.ViewModels"
...>
  <Window.Resources>
    <DataTemplate DataType="{x:Type models:MyViewModel}">
      <Button Content="Execute MyRoutedCommand" Command="model:ViewCommands.MyRoutedCommand" />
    </DataTemplate>
  </Window.Resources>
  <Grid>
    <baseViews:ViewModelControl Content="{Binding}" />
  </Grid>
</Window>


That's it. It works very nicely, try it.

I think I'll be posting a more complete article about this soon. In the mean time:

- What do you think?
- Want to see some real code?

Monday, September 21, 2009

TEAM's Db4o Management Studio v0.1.0 is out

Many times in the latest couple of months I've found my self hoping for a tool that would allow me to inspect a db4o database without using the classes that were used to save the data.

One of these situations is when I'm migrating an old classes' schema into a new one, and I really need to see what's inside the database to implement the migration.

After so much hoping and dissapointment on the Db4o Object Manager, I decided to implement a simple tool to do the job. The result is a very simple (and crude) application.

Don't expect anything fancy, but please, send any comments and suggestions, and feel free to copy the idea and make a better tool. The db4o community will thank you.

You can get the application from sourceforge here

Thursday, August 27, 2009

TEAM's TimeTracker v2.2.0 is out

A long time ago I built an application to manage the time me and my co-workers spent at work. I built the tool to be very simplistic and useful.

Although I published it in SourceForge since the beginning, I didn't have notice of any other users of the application until recently, on July 15th 2009, when Softpedia included the application in their database:



From that moment on some people started using it and it became obvious that the errors which we were already used to were a blocking issue for most people out there. That's why I've spent some time fixing those errors (and hopefully not introducing new ones).

Thanks to Randy Schultz for reporting most of the issues, and thanks to my former co-workers in Expectra for using the application no matter what, the TEAM's TimeTracker v2.2.0 is available at SourceForge:

http://sourceforge.net/projects/wpf-timetracker/

This version is able to automatically migrate the old data you had if you were using v0.1.0.

I hope you like it.