# 09 Mayıs 2007 Çarşamba
Ayende, in his post on virtual entry barriers / learning curve of Castle pieces, said:
One of the main differences between OSS and Commercial software is the amount of time that is invested in the frills. Active Record and NHibernate has a designer, which is nice, but it is not a level 1 priority to any of the people using either Active Record or NHibernate. The reason is that both those frameworks were built knowing that a designer is not something that you should need in order to work with them.
That is, of course, super true for MonoRail and when I started working on ActiveWriter, I said "ActiveRecord is so simple, no one gonna use a code generator for it". Now I think somewhat different, in the context of O/RM designers.

When I think of working with ActiveRecord, I see it in two different parts. First is the sceleton of an entity; all the attributes tagging the class, properties and fields to describe the model to ActiveRecord and then NHibernate, eventually.

    [ActiveRecord()]

    public partial class Entity : ActiveRecordBase {

 

        private int _key;

 

        [PrimaryKey(PrimaryKeyType.Native, ColumnType="Int32")]

        public int Key {

            get {

                return this._key;

            }

            set {

                this._key = value;

            }

        }

    }


This code is a no brainer to write and AR has quite good documentation to get you there easily. But it's so repetative that it's the perfect place for using a designer. I don't say that people using ActiveRecord should forget all the attributes to define an entity alltogether, but once you studied the underlying workings of the framework I believe even the most basic framework can use a designer when it comes to the brute force part of the code. After all, you are designing some entitities and that's what a designer do best.

One problem here is that it's not easy to modify this kind of generated code. Thanks to 2.0, partial classes help great when adding new functionality, but it's impossible to modify generated getters and setters. DSL Tools is using the term "double derived" for the approach used to solve this problem, use an inherited empty entity instead of the original one around to make it possible to override properties. This model works fine in DSL Tools context but might make real world entities complicated. This one and solutions like this which makes code more bloated are, I believe, the dark side of code generating designers.

There is also the process of giving the entity some brains; validation, query helper etc. I, again, can see the value of a designer here. ActiveWriter can generate entities with ActiveRecord validators (and there's a JIRA entry waiting to port it to Castle validators). Thanks to his permission, I'll integrate Ayende's Generator into ActiveWriter to make it generate code with all the typed query functionality but ActiveWriter of course won't be writing the query.

The other part of working with ActiveRecord is knowing what the framework gives you, what does it do on behalf, what are the list of things to know beforehand to know before it starts persisting. You should know about lazy loading, order of saving, inverse relations etc. This is the point when you instruct the framework to manage what you designed before, and I think where a designer should keep it's hands off. ActiveWriter, and tools alike, should help developers to define metadata. They should not act like metadata manipulators to do the programming. I consider Ayende's comments above true in this part of the usage. A good O/RM designer should work without getting the way, and shouldn't make the user careless by doing the thinking on behalf.

posted on 09 Mayıs 2007 Çarşamba 14:42:35 UTC  #   
# 25 Nisan 2007 Çarşamba
Both about MonoRail, actually.
Seeing your work used in screencasts is priceless.

posted on 25 Nisan 2007 Çarşamba 08:57:28 UTC  #   
# 11 Nisan 2007 Çarşamba
I'm helping a client to customize and implenet MSF for Agile. As always, it's virtually impossible to find information on details when it comes to MSF. I find Scrum much more documented in this regard, there are tons of information on nearly very aspect of Scrum (web sites, screencasts, papers etc.) while you have to dig MSF v4 Forum for some tidbits.

One possible solution to info scarcity on MSF is Microsoft Solutions Framework Essentials, a nice book by Michael S. V. Turner. In the book, each track is marked with some deliverables but it's not clear who is doing what. I tried to construct a martix, some based on the info on the book and some based on my understanding of the concepts. I'm not 100% sure on Stabilization and Deployment tracks, so any corrections / suggestions are welcome.

MSF Agile Deliverables Matrix 1.0.pdf (229.36 KB)



Update: Michael Tsai makes a correction: "According to Mike Turner's book, I think Product Management should be the advocacy for Vison/scope document, instead of Program Management. See Figure 4-4 and p. 169-170."
There are also some suggestions on the MSF Forums thread on the matrix. I'll incorporate suggestions to the chart in the near future.
posted on 11 Nisan 2007 Çarşamba 20:28:55 UTC  #   
# 18 Mart 2007 Pazar
Download here.

What's new:
  • Generics support (ActiveRecordBase<T> & ActiveRecordValidationBase<T>) (Generics is the default in the designer)
  • VB.NET seems OK (Not tested extensively).
  • Auto-sensing project type (C# or VB.NET) for code generation. You don't have to set that in the model anymore.
  • New ActiveWriter Class Details toolwindow. Can be used for rapidly adding class properties. (Idea: Ayende)
  • AR validators are supported for each property (not for field, key, composite key, timestamp or version) through a designer.
  • Ability to customize the base class. You can substitude your own base class from the editor or generate classes without a base class.
  • Ability to customize the source property name for associations. This is necessary for hierarchical objects, where they point to themselves, and using the class name resulted in un-compilable code in previous build. (Reported By: Ayende)
  • More domain consistency check through validations when opening / saving.
  • Applying pluralizing rules to the table name from the entity name if not specified. (Idea: Ayende)
  • Ability to select a property for optional DebuggerDisplay attribute.
  • Ability to decorate classes with GeneratedCodeAttribute.
  • No more setting Custom Tool property of an .actiw file to ActiveWriterCodeGenerator manually after creating the file. It's done automatically. (Thanks: Bogdan Pietroiu)
  • Key icon decorator on class shapes if a primary or composite key property exists (pure cosmetic).
  • Key icon decorator on class shapes if at least a property has validator(s) set (pure cosmetic).
  • Connector shapes changed to a more-UML-like notation.
  • Extended nullable support. You may choose between nullables through external Nullables library (1.1 style) or native nullables usage of 2.0 framework.
  • Some added properties to support changes (not all) in Castle trunk for ActiveRecordAttribute, PropertyAttribute etc.
  • Built with VS SDK v4. Includes new and improved version of DSL Tools redistributables.
What's crippled:
  • Using Output window less when doing drag-drop from Server Explorer to prevent a bug.
Known bugs / problems:
  • On international versions of VisualStudio, Drag'n drop support from Server Explorer generates entitites but not properties. You may create entities manually as a workaround.
  • Randomly, when you drag tables from Server Explorer, design surface gizes an error and cannot render any entities any more. You may save and re-open your .actiw file and it will catch up.
Screenshot below displays:
  • Validation support
  • Generic code generation
  • Nullables
  • Class details tool window
  • Visual hints on diagram elements
posted on 18 Mart 2007 Pazar 15:59:05 UTC  #   
# 12 Mart 2007 Pazartesi
I was using a private SVN for ActiveWriter and thanks to Hammet, the source is now available through Castle Contrib Repository.
Having source on an open repository is great. AW now has it's own Ohloh page :)
  • Codebase: 27,938 LOC (Most of them generated by DSL Tools, actually:)
  • Effort (est.): 7 Person Years
  • Project Cost: $362,806
I feel good! :)

posted on 12 Mart 2007 Pazartesi 10:11:10 UTC  #   
# 08 Mart 2007 Perşembe

I was doing a code review for a client and something like the following was everywhere:

    command.CommandText = "EXEC ManageBlogs;2 '" + blogName + "'";

    command.ExecuteReader();


Yes, they don't use parametrized queries. They don't even mark the command as a SP but that's the usual bad practice I happen to see everywhere. But what the heck ";2" stands for? I remember reading something like that, let's fire Books Online for Create Procedure statement (T-SQL 2000, which my client use):

CREATE PROC [ EDURE ] [ owner. ] procedure_name [ ; number ]

;number

Is an optional integer used to group procedures of the same name so they can be dropped together with a single DROP PROCEDURE statement. For example, the procedures used with an application called orders may be named orderproc;1, orderproc;2, and so on. The statement DROP PROCEDURE orderproc drops the entire group. If the name contains delimited identifiers, the number should not be included as part of the identifier; use the appropriate delimiter around procedure_name only.



...and here's the 2005 version:

CREATE { PROC | PROCEDURE } [schema_name.] procedure_name [ ; number ]
...
; number

Is an optional integer that is used to group procedures of the same name. These grouped procedures can be dropped together by using one DROP PROCEDURE statement. For example, an application called orders might use procedures named orderproc;1, orderproc;2, and so on. The DROP PROCEDURE orderproc statement drops the whole group. If the name contains delimited identifiers, the number should not be included as part of the identifier; use the appropriate delimiter around only procedure_name.

Numbered stored procedures have the following restrictions:

  • Cannot use xml or CLR user-defined types as the data types.

  • Cannot create a plan guide on a numbered stored procedure.

Note:

This feature will be removed in a future version of Microsoft SQL Server. Avoid using this feature in new development work, and plan to modify applications that currently use this feature.

I believe this is something from the archaic days when all the development happened on the DB, that's why SP's for in the first place, isn't it? I even bet this is a fossil syntax leftover from the Sybase SQL days. Good to see that this will be dropped, but it should have already been with SQL 2005.

So, what was my client thinking? Since they use SP's extensively, they use this as a method overload. SP name stands for the static class and the number is something like different methods to call. They use 1 for INSERT, 2 for SELECT and 3 for DELETE and so on.

CREATE PROCEDURE ManageBlogs;1

    @Name varchar(50)

AS

    INSERT INTO Blogs (blog_name) VALUES (@Name)

GO

 

CREATE PROCEDURE ManageBlogs;2

AS

    SELECT * FROM Blogs

GO

 

CREATE PROCEDURE ManageBlogs;3

    @Id int

AS

    DELETE FROM Blogs WHERE blog_id = @Id

GO

Usage?

Exec ManageBlogs -- Error

 

Exec ManageBlogs 'MyBlog' -- Executes ;1

 

Exec ManageBlogs;1 'MyBlog' -- Executes ;1

 

Exec ManageBlogs;2 -- Executes ;2

 

Exec [ManageBlogs];2 -- Executes ;2

 

Exec [ManageBlogs;2] -- Error

Total chaos :) And I was quick to find ;1's that don't insert in some SP's, so they broke their own rules already.

VS 2005 designer picks up only the first one:



Hey, even Management Studio doesn't support numbered SP's:



I believe I have enough evidence to to convince my client that this is pure evil :)
posted on 08 Mart 2007 Perşembe 10:46:34 UTC  #   
# 30 Ocak 2007 Salı
Last week, Edward Bakker started summarizing some notes and resources on Software Factories, then Jezz Santos added this one on "When would you build one". (Their latest posts have a cyclic dependency, by the way :) I don't know if people (apart from these two guys. They're already into it to their neck :) are more talkative on SF notion lately or my doors of perception are more open to this kind of posts since I'm trying to build one myself, but I started seeing more and more on this subject.

I remember seeing a discussion between Grady (an IBM Fellow, as his blog says) and Greenfield, Cook, Wills and Kent on the UML vs SF kind of debate (and I assure you I didn't have a clue back then how important things they're talking on). Then I interested in code generation. Then I had to use NHibernate for a little project. Then I wanted to generate .hbm.xml documents in VS. Then I thought I prefer attribute decorations rather than XML declarations. Then I found out DSL Tools in this post (Sequence ended in mid 2006. Quite late for me, huh?).

Now, with DSL Tools in hand, I feel like I can take over the world :) Seriously, check the comments for this post. People want tools for their everyday needs. Put some guidance in, integrate with the IDE and they're willing to do the rest. Learning curve might be a little steep but anybody dreaming a tool to generate some code or project instruments or a custom domain intelligent enough to do some repetitive / predefined work may start building it right now or use existing ones, be it DSL Tools, GAT / GAX or one of the available software factories.

posted on 30 Ocak 2007 Salı 00:23:29 UTC  #   
# 29 Ocak 2007 Pazartesi
It sometimes get frustrating when you debug your project through another instance of Visual Studio, especially if you manipulate the "active" DTE within your debug project. I somehow ended up to the following when getting a reference to DTE:

System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.8.0");


It worked most of the time, but "not all the time" means you may add a project to the solution where your code resides (the parent VS instance), rather than where the debugging session is. So, after some research, DTE code turned into this:

[DllImport("ole32.dll")]

public static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable prot);


[DllImport("ole32.dll")]

public static extern int CreateBindCtx(int reserved, out IBindCtx ppbc);


[CLSCompliant(false)]

public static DTE GetDTE(string processID)

{

    IRunningObjectTable prot;

    IEnumMoniker pMonkEnum;

 

    string progID = "!VisualStudio.DTE.8.0:" + processID;

 

    GetRunningObjectTable(0, out prot);

    prot.EnumRunning(out pMonkEnum);

    pMonkEnum.Reset();

 

    IntPtr fetched = IntPtr.Zero;

    IMoniker[] pmon = new IMoniker[1];

    while (pMonkEnum.Next(1, pmon, fetched) == 0)

    {

        IBindCtx pCtx;

        CreateBindCtx(0, out pCtx);

        string str;

        pmon[0].GetDisplayName(pCtx, null, out str);

        if (str == progID)

        {

            object objReturnObject;

            prot.GetObject(pmon[0], out objReturnObject);

            DTE ide = (DTE)objReturnObject;

            return ide;

        }

    }

 

    return null;

}

posted on 29 Ocak 2007 Pazartesi 22:17:43 UTC  #   
I was trying to solve the Custom Tool property issue with .actiw files in ActiveWriter, as suggested by Bogdan Pietroiu months ago, and spent a clear hour trying to figure how to inject my own registry keys into WiX setup project of DSL Tools. I modified the .vstemplate for .actiw files to include the following:

...

<CustomParameters>

  <CustomParameter Name="$itemproperties$" Value="CustomTool" />

  <CustomParameter Name="$CustomTool$" Value="ActiveWriterCodeGenerator" />

</CustomParameters>

...


and thought that the file, when added to the project, will have Custom Tool property already set. I was appearently wrong (documentation says it should work).

Bogdan's suggestion was to have a key named after the file extension under Generators\{Language}, and I manually confirmed that it works great. So, how to automate the process of adding this reg key through the setup? WiX Toolkit documentation shows the way, so I copied Registry.wxs to have my own key registered.

<?xml version="1.0" encoding="utf-8"?>

<Wix xmlns='http://schemas.microsoft.com/wix/2003/01/wi'>

  <Fragment Id="CustomToolFragment">

    <FeatureRef Id="DefaultFeature">

      <ComponentRef Id="_ActiveWriterCTReg" />

    </FeatureRef>

    <DirectoryRef Id="TARGETDIR">

      <Component Id="_ActiveWriterCTReg" Guid="{some GUID}">

        <Registry Root='HKLM' Key='Software\Microsoft\VisualStudio\8.0\Generators\{164b10b9-b200-11d0-8c61-00a0c91e29d5}\.actiw' Id='{some GUID}' Type='string' Value='ActiveWriterCodeGenerator' />

        <Registry Root='HKLM' Key='Software\Microsoft\VisualStudio\8.0\Generators\{fae04ec1-301f-11d3-bf4b-00c04f79efbc}\.actiw' Id='{some GUID}' Type='string' Value='ActiveWriterCodeGenerator' />

      </Component>

    </DirectoryRef>

  </Fragment>

</Wix>


<Registry> elements define the key to be added, as you may have guessed. Anyway, although I changed the build action on the .wxs and although it seems that Candle and Light picked up the file, the installer didn't add the registry key. So? Orca to the rescue. You should check Component and Registry tables in .msi file to check if your key slipped in, and Orca shows them quite detailed. In my case, though, it shows the absence of my additions.

Long story (not so) short, it seems that I should examine Registry.tt as the first step, but didn't. To include your ComponentRef in DefaultFeature, you should have your Fragment as FragmentRef in Main.wxs . So, you should add each of your custom fragment in the list defined in customFragmentIds in InstallerDefinitions.dslsetup as shown below:

<installerDefinition xmlns="http://schemas.microsoft.com/VisualStudio/2005/DslTools/InstallerDefinitionModel"

  ...

  customFragmentIds="CustomToolFragment">

I hope this info helps someone.

posted on 29 Ocak 2007 Pazartesi 21:13:31 UTC  #