Using a Sybase with S#arp Architecture and nHibernate

This article will discuss on how I achieved using a Sybase database alongside SQL Server with S#arp Architecture / nHibernate.   In this article I would assume that you use S#arp and have already a running project where you want to include Sybase in your scenario.  So lets start.

1. Create your Sybase Connection String

Go to your web config and add a connection string like such

  <connectionStrings>
    <add name="SybaseConnectionString" connectionString="Data Source='{YOURSYBASEDATABASE}';Port=5000;UID='{xxxxxx}';Password='{xxxxxx}';Database='{SomeDatabase}'"/>
  </connectionStrings>

2. Create a Domain for your Sybase Tables

For this demo we will reference a table from a Sybase database called Activity.

Sybase

First we create a class library project to separate you existing Domain to your Sybase Domain.  We will call it Sybase.Domain

2 Sybase Domain

In that project we will create a class to represent the “Activity” table

namespace Sybase.Domain
{
    public class Activity
    {
        public virtual string Code { getset; }

        public virtual string Name { getset; }

        public virtual string Type { getset; }

        public virtual string SubType { getset; }
    }
}

3. Create a class to grab that Connection String

For a cleaner implementation we create an Infrastructure Class Library Project, under the Infrastructure Solution Folder and call it Sybase.Infrastructure. This project will be a container for infrastructure related items such as repositories.  We will also create an Interface for it so we don’t reference Infrastructure in our main Web project and use the already exposed Domain.  Having said that we will be creating that Interface in the Sybase.Domain project.

At this stage import the highlighted references on the image below

Lets create your RepositoryConfiguration Class which will expose your connection string

using System.Configuration;
using Sybase.Domain.Contracts.Configuration;

namespace Sybase.Infrastructure
{
    public class RepositoryConfiguration : IRepositoryConfiguration
    {
        public string ConnectionString
        {
            get
            {
                string connectionString = ConfigurationManager.ConnectionStrings["SybaseConnectionString"].ConnectionString;

                return connectionString;
            }
        }
    }
}

Then the interface in your Sybase.Domain project

namespace Sybase.Domain.Contracts.Configuration
{
    public interface IRepositoryConfiguration
    {
        string ConnectionString { get; }
    }
}

3 Get your connection string

4. Create a mapping Extension

Now you have your domain we need to create a reusable Mapping mechanism so Sybase column names map properly to the Sybase Domain Classes.  At this stage we will be creating it in another class library project which we call Framework, this will contain Framework Related Items like Referenced Assemblies, Extensions as well as Helpers.  Let’s call it Demo.Framework.

Inside the project we create and Extensions folder and create our AutoMappingExtension class

using System;
using System.Collections.Generic;
using System.Data;

namespace Demo.Framework.Extensions
{
    public static class AutoMappingExtension
    {
        public static IList<T> Map<T>(this IDataReader dataReader) where T : new()
        {
            IList<T> list = new List<T>();

            if (dataReader != null)
            {
                while (dataReader.Read())
                {
                    var destination = new T();
                    Type destinationType = destination.GetType();

                    for (int i = 0; i < dataReader.FieldCount; i++)
                    {
                        string sourceFieldName = dataReader.GetName(i);
                        string destinationPropertyName = sourceFieldName.InflectTo().Pascalized;

                        var destinationProperty = destinationType.GetProperty(destinationPropertyName);

                        if (destinationProperty != null && destinationProperty.CanWrite)
                        {
                            object destinationValue = FormatDestinationValue(dataReader[i], destinationProperty.PropertyType.GetUnderlyingType());
                            destinationProperty.SetValue(destination, destinationValue, null);
                        }
                    }

                    list.Add(destination);
                }

                dataReader.Close();
            }

            return list;
        }

        public static Type GetUnderlyingType(this Type source)
        {
            if (source.IsGenericType && (source.GetGenericTypeDefinition() == typeof(Nullable<>)))
            {
                // source is a Nullable type so return its underlying type
                return Nullable.GetUnderlyingType(source);
            }

            // source isn't a Nullable type so just return the original type
            return source;
        }

        private static object FormatDestinationValue(object value, Type destinationType)
        {
            if (value == null || value == DBNull.Value)
            {
                return null;
            }

            TypeCode destinationTypeCode = Type.GetTypeCode(destinationType);

            switch (destinationTypeCode)
            {
                case TypeCode.String:
                    value = value.ToString().TrimEnd();
                    break;

                case TypeCode.DateTime:
                    value = Convert.ToDateTime(value);
                    break;
            }

            return value;
        }
    }
}

Please note that we will use Inflector Extension (http://brendanjerwin.com/blog/2010/02/25/inflector-extension/) to provides a convenient Inflect() extension method on string and int data types

4 Automapping Extension

5. Create your first Sybase Repository

Now you have everything you need lets create your first Repository which will be in your Sybase.Infrastructure project, Lets call it ActivitiesRepository.  You will also need to create your Interface in Sybase.Domain project.

Lets do a simple Get By, so here is your method

using System;
using Sybase.Domain.Contracts.Configuration;
using System.Collections.Generic;
using Sybase.Domain;
using Sybase.Data.AseClient;
using Sybase.Domain.Repositories;
using System.Data;
using Demo.Framework.Extensions;
namespace Sybase.Infrastructure
{
    public class ActivitiesRepository : IActivitiesRepository
    {
        private readonly IRepositoryConfiguration repositoryConfiguration;
        public ActivitiesRepository(IRepositoryConfiguration repositoryConfiguration)
        {
            this.repositoryConfiguration = repositoryConfiguration;
        }
        public IList<Activity> GetBy(string activityCode)
        {
            try
            {
                IList<Activity> activities;

                using (var connection = new AseConnection(repositoryConfiguration.ConnectionString))
                {
                    var command = connection.CreateCommand();
                    command.CommandType = CommandType.Text;

                    command.CommandText = @"SELECT
                                            activity_code as Code,
                                            activity_name as Name,
                                            activity_type as Type,
                                            activiy_subtype as SubType
                                            FROM dbo.activity 
                                            WHERE activity_code = '" + activityCode + "'";

                    connection.Open();

                    using (var dataReader = command.ExecuteReader())
                    {
                        activities = dataReader.Map<Activity>();
                    }
                }

                return activities;
            }
            catch (Exception ex)
            {
                // TODO: Log exception
                return null;
            }
        }
    }
}

Then your Interface in your Sybase.Domain project

using System.Collections.Generic;

namespace Sybase.Domain.Repositories
{
    public interface IActivitiesRepository
    {
        IList<Activity> GetBy(string activityCode);
    }
}

5 Repository

6. Register the projects you just created in CastleWindsor’s Component Registrar

Go to your Presentation Layer, in this case its Demo.Web.Mvc.  In the CastleWindsor Folder there is a Class called ComponentRegistrar.  Add the following codes to under the AddQueryObjectsTo object

container.Register(
    AllTypes.FromAssemblyNamed("Sybase.Infrastructure")
        .Pick()
        .WithService.FirstNonGenericCoreInterface("Sybase.Domain"));

You also need to reference your Sybase Related Projects here

6 Reference Your Sybase Projects

7. Create your query object and test your code

In this instance we create a method in your controllers queries and call it GetActivities.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using SharpArch.NHibernate;

namespace Demo.Web.Mvc.Controllers.Queries
{
    public class HomeQuery : NHibernateQuery
    {
        private readonly Sybase.Domain.Contracts.Repositories.IActivitiesRepository activitiesRepository;
        public HomeQuery(
              Sybase.Domain.Contracts.Repositories.IActivitiesRepository activitiesRepository
            )
        {
            this.activitiesRepository = activitiesRepository;
        }

        public void GetActivities(string activityCode)
        {
            activitiesRepository.GetBy(activityCode);
        }

    }
}

Now run and test your code.

Simple TSQL and C# Entity Generator for S#arp Architecture

Recently we started a big project which uses S#arp Architecture and for those who does not know what it is you can go to the site (http://www.sharparchitecture.net/) and have a read, but in a gist it is an open source architectural foundation that uses ASP.NET MVC framework with NHibernate.

The following principles of this architecture are Domain Driven Design Focus, Loosely coupled, Preconfigured Infrastructure and Open Ended Presentation that means having those principles in mind the developer can concentrate more on Domain and User Experince part of the application that is being developed.

Having said that we used this open-source architecture to leverage on its principles and now we are on the first phase of the project where we are building the Domain layer where we define all the entities needed.  If you have a big database this will be a tedious task mapping tables and columns to a classes so I created a TSQL script to generate those entities so that I’ll just copy and paste the output to a cs file and were ready to go.

DECLARE @TableName varchar(200)
DECLARE @ProjectName varchar(200) = '<<<YourApplicationName>>>.Domain'
DECLARE @DataType varchar(200)
DECLARE @ColumnName varchar(200)
DECLARE @IsNullable varchar(200)
DECLARE @AppDataType varchar(200) = 'String'
DECLARE @ConstraintType varchar(200) 
DECLARE @ReferringTable varchar(200) 

DECLARE ClassGenerator CURSOR

--Get all Tables
FOR SELECT TABLE_NAME from <<<YourDatabaseName>>>.INFORMATION_SCHEMA.TABLES where TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME
OPEN ClassGenerator
FETCH NEXT FROM ClassGenerator
INTO @TableName

PRINT 'namespace ' + @ProjectName
PRINT '{'
PRINT ' using System;'
PRINT ' using SharpArch.Domain.DomainModel;'

WHILE @@FETCH_STATUS = 0
BEGIN 

		PRINT ' public class ' + dbo.Singularize(@TableName) + ' : Entity'
		PRINT ' {'

		DECLARE EntityGenerator CURSOR
		FOR 

		--Get all columns and their key types from all the tables
		SELECT 
		COL.COLUMN_NAME, 
		COL.IS_NULLABLE, 
		COL.DATA_TYPE, 
		CST.CONSTRAINT_TYPE,
		KCU.TABLE_NAME AS REFERENTIAL_TABLE_SOURCE
		FROM 
		INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU
		INNER JOIN 
		INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RCN
		ON KCU.CONSTRAINT_NAME = RCN.UNIQUE_CONSTRAINT_NAME 
		RIGHT OUTER JOIN 
		INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU2
		INNER JOIN 
		INFORMATION_SCHEMA.TABLE_CONSTRAINTS CST
		ON KCU2.CONSTRAINT_NAME = CST.CONSTRAINT_NAME 
		AND KCU2.TABLE_NAME = CST.TABLE_NAME 
		ON RCN.CONSTRAINT_NAME = KCU2.CONSTRAINT_NAME 
		RIGHT OUTER JOIN 
		INFORMATION_SCHEMA.COLUMNS COL
		ON KCU2.TABLE_NAME = COL.TABLE_NAME 
		AND KCU2.COLUMN_NAME = COL.COLUMN_NAME
		WHERE 
		COL.TABLE_NAME = @TableName
		ORDER BY 
		COL.TABLE_NAME

		OPEN EntityGenerator
		FETCH NEXT FROM EntityGenerator
		INTO @ColumnName, @IsNullable, @DataType, @ConstraintType, @ReferringTable

		WHILE @@FETCH_STATUS = 0
		BEGIN 

			IF @ConstraintType <> 'PRIMARY KEY' OR @ConstraintType IS NULL
			BEGIN
				IF @ConstraintType = 'FOREIGN KEY'
				BEGIN
					PRINT ' public virtual ' + dbo.Singularize(@ReferringTable) + ' '  + dbo.Singularize(@ReferringTable) + ' { get; set; }' 
				END
				ELSE
				BEGIN

					--SQL to .NET Data Type Mapping
					IF @DataType = 'bigint' BEGIN SET @AppDataType = 'Int64' END
					IF @DataType = 'binary' BEGIN SET @AppDataType = 'Byte[]' END
					IF @DataType = 'bit' BEGIN SET @AppDataType = 'Boolean' END
					IF @DataType = 'char' BEGIN SET @AppDataType = 'String' END
					IF @DataType = 'date' BEGIN SET @AppDataType = 'DateTime' END
					IF @DataType = 'datetime' BEGIN SET @AppDataType = 'DateTime' END
					IF @DataType = 'datetimeoffset' BEGIN SET @AppDataType = 'DateTimeOffset' END
					IF @DataType = 'decimal' BEGIN SET @AppDataType = 'decimal' END
					IF @DataType = 'float' BEGIN SET @AppDataType = 'Double' END
					IF @DataType = 'image' BEGIN SET @AppDataType = 'Byte[]' END
					IF @DataType = 'int' BEGIN SET @AppDataType = 'Int32' END
					IF @DataType = 'money' BEGIN SET @AppDataType = 'Decimal' END
					IF @DataType = 'nchar' BEGIN SET @AppDataType = 'String' END
					IF @DataType = 'ntext' BEGIN SET @AppDataType = 'String' END
					IF @DataType = 'numeric' BEGIN SET @AppDataType = 'Decimal' END
					IF @DataType = 'nvarchar' BEGIN SET @AppDataType = 'String' END
					IF @DataType = 'real' BEGIN SET @AppDataType = 'Single' END
					IF @DataType = 'rowversion' BEGIN SET @AppDataType = 'Byte[]' END
					IF @DataType = 'smalldatetime' BEGIN SET @AppDataType = 'DateTime' END
					IF @DataType = 'smallint' BEGIN SET @AppDataType = 'Int16' END
					IF @DataType = 'smallmoney' BEGIN SET @AppDataType = 'Decimal' END
					IF @DataType = 'sql_variant' BEGIN SET @AppDataType = 'Object' END
					IF @DataType = 'text' BEGIN SET @AppDataType = 'String' END
					IF @DataType = 'time' BEGIN SET @AppDataType = 'TimeSpan' END
					IF @DataType = 'timestamp' BEGIN SET @AppDataType = 'Byte[]' END
					IF @DataType = 'tinyint' BEGIN SET @AppDataType = 'Byte' END
					IF @DataType = 'uniqueidentifier' BEGIN SET @AppDataType = 'Guid' END
					IF @DataType = 'varbinary' BEGIN SET @AppDataType = 'Byte[]' END
					IF @DataType = 'varchar' BEGIN SET @AppDataType = 'String' END
					IF @DataType = 'xml' BEGIN SET @AppDataType = 'Xml' END

					IF @IsNullable = 'YES' AND @AppDataType <> 'Byte[]' AND @AppDataType <> 'String'
					BEGIN 
						PRINT ' public virtual ' + @AppDataType + '? ' + @ColumnName + ' { get; set; }'
					END
					ELSE
					BEGIN
						PRINT ' public virtual ' + @AppDataType + ' ' + @ColumnName + ' { get; set; }'
					END
				END
			END
			FETCH NEXT FROM EntityGenerator
			INTO @ColumnName, @IsNullable, @DataType, @ConstraintType, @ReferringTable

		END
		CLOSE EntityGenerator
		DEALLOCATE EntityGenerator

	PRINT ' }'

	FETCH NEXT FROM ClassGenerator

INTO @TableName
END
PRINT '}'
CLOSE ClassGenerator
DEALLOCATE ClassGenerator

Now I noticed wouldn’t it be cleaner to create each entity in different class files? So I created a console application to do that which separates each entity to a file.  And here is the code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.IO;

class Program
{
    static void Main(string[] args)
    {
        string sConnString = "Data Source=<<<YourDatabaseServer>>>;Initial Catalog=<<<YourDatabase>>;Integrated Security=SSPI";
        SqlConnection oSQLConn1 = new SqlConnection(sConnString);
        SqlDataReader oReader = null;
        string sProjectName = "<<<YourProjectName>>>.Domain";
        string sGeneratedCodeLocation = @"C:\<<<YourProjectFolder>>>";

        oSQLConn1.Open();

        SqlCommand oCommand = new SqlCommand("SELECT TABLE_NAME, dbo.Singularize(TABLE_NAME) as SINGULARIZED_TABLE from INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME", oSQLConn1);

        oReader = oCommand.ExecuteReader();

        while (oReader.Read())
        {
            string sTableName = oReader[0].ToString();
            string sSingularizedTableName = oReader[1].ToString();
            SqlConnection oSQLConn2 = new SqlConnection(sConnString);
            SqlDataReader oItemReader = null;

            oSQLConn2.Open();

            SqlCommand oItemCommand =
            new SqlCommand(@"SELECT 
     COL.COLUMN_NAME, 
     COL.IS_NULLABLE, 
     COL.DATA_TYPE, 
     CST.CONSTRAINT_TYPE,
     dbo.Singularize(KCU.TABLE_NAME) AS REFERENTIAL_TABLE_SOURCE
     FROM 
     INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU
     INNER JOIN 
     INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RCN
     ON KCU.CONSTRAINT_NAME = RCN.UNIQUE_CONSTRAINT_NAME 
     RIGHT OUTER JOIN 
     INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU2
     INNER JOIN 
     INFORMATION_SCHEMA.TABLE_CONSTRAINTS CST
     ON KCU2.CONSTRAINT_NAME = CST.CONSTRAINT_NAME 
     AND KCU2.TABLE_NAME = CST.TABLE_NAME 
     ON RCN.CONSTRAINT_NAME = KCU2.CONSTRAINT_NAME 
     RIGHT OUTER JOIN 
     INFORMATION_SCHEMA.COLUMNS COL
     ON KCU2.TABLE_NAME = COL.TABLE_NAME 
     AND KCU2.COLUMN_NAME = COL.COLUMN_NAME
     WHERE 
     COL.TABLE_NAME = '" + sTableName +
            @"' ORDER BY 
     COL.TABLE_NAME", oSQLConn2);

            oItemReader = oItemCommand.ExecuteReader();
            TextWriter oCSFile = new StreamWriter(sGeneratedCodeLocation + sSingularizedTableName + ".cs");

            oCSFile.WriteLine("namespace " + sProjectName);
            oCSFile.WriteLine("{");
            oCSFile.WriteLine("\tusing System;");
            oCSFile.WriteLine("\tusing SharpArch.Domain.DomainModel;");

            oCSFile.WriteLine("\tpublic class " + sSingularizedTableName + " : Entity");
            oCSFile.WriteLine("\t{");

            while (oItemReader.Read())
            {
                string sAppDataType = "String";

                string sColumnName = oItemReader[0].ToString();
                string sIsNullable = oItemReader[1].ToString();
                string sDataType = oItemReader[2].ToString();
                string sConstraintType = oItemReader[3].ToString();
                string sReferringTable = oItemReader[4].ToString();

                if (sConstraintType != "PRIMARY KEY" || sConstraintType == null)
                {
                    if (sConstraintType == "FOREIGN KEY")
                    {
                        oCSFile.WriteLine("\t\tpublic virtual " + sReferringTable + " " + sReferringTable + " { get; set; }");
                    }
                    else
                    {
                        //SQL to .NET Data Type Mapping
                        if (sDataType == "bigint") sAppDataType = "Int64";
                        if (sDataType == "binary") sAppDataType = "Byte[]";
                        if (sDataType == "bit") sAppDataType = "Boolean";
                        if (sDataType == "char") sAppDataType = "String";
                        if (sDataType == "date") sAppDataType = "DateTime";
                        if (sDataType == "datetime") sAppDataType = "DateTime";
                        if (sDataType == "datetimeoffset") sAppDataType = "DateTimeOffset";
                        if (sDataType == "decimal") sAppDataType = "decimal";
                        if (sDataType == "float") sAppDataType = "Double";
                        if (sDataType == "image") sAppDataType = "Byte[]";
                        if (sDataType == "int") sAppDataType = "Int32";
                        if (sDataType == "money") sAppDataType = "Decimal";
                        if (sDataType == "nchar") sAppDataType = "String";
                        if (sDataType == "ntext") sAppDataType = "String";
                        if (sDataType == "numeric") sAppDataType = "Decimal";
                        if (sDataType == "nvarchar") sAppDataType = "String";
                        if (sDataType == "real") sAppDataType = "Single";
                        if (sDataType == "rowversion") sAppDataType = "Byte[]";
                        if (sDataType == "smalldatetime") sAppDataType = "DateTime";
                        if (sDataType == "smallint") sAppDataType = "Int16";
                        if (sDataType == "smallmoney") sAppDataType = "Decimal";
                        if (sDataType == "sql_variant") sAppDataType = "Object";
                        if (sDataType == "text") sAppDataType = "String";
                        if (sDataType == "time") sAppDataType = "TimeSpan";
                        if (sDataType == "timestamp") sAppDataType = "Byte[]";
                        if (sDataType == "tinyint") sAppDataType = "Byte";
                        if (sDataType == "uniqueidentifier") sAppDataType = "Guid";
                        if (sDataType == "varbinary") sAppDataType = "Byte[]";
                        if (sDataType == "varchar") sAppDataType = "String";
                        if (sDataType == "xml") sAppDataType = "Xml";

                        if (sIsNullable == "YES" && sAppDataType != "Byte[]" && sAppDataType != "String")
                        {
                            oCSFile.WriteLine("\t\tpublic virtual " + sAppDataType + "? " + sColumnName + " { get; set; }");
                        }
                        else
                        {
                            oCSFile.WriteLine("\t\tpublic virtual " + sAppDataType + " " + sColumnName + " { get; set; }");
                        }
                    }

                }
            }
            oCSFile.WriteLine("\t}");
            if (oItemReader != null) oItemReader.Close();
            if (oSQLConn2 != null) oSQLConn2.Close();

            oCSFile.WriteLine("}");
            oCSFile.Close();
        }
        Console.ReadLine();

        if (oReader != null) oReader.Close();
        if (oSQLConn1 != null) oSQLConn1.Close();
    }
}

Now lets dissect the codes, if you noticed I used a Singularize Function to Singularize Table Names I have posted a code for that which you can find here

http://anyrest.wordpress.com/2011/09/13/singularize-function-in-tsql/.

Now let’s go to the queries, you will notice that there is a complex join in how we get our data regarding our data structure which can be easily extracted from the Information Schema, if you are interested on what other items can be extracted from it have a read here

http://msdn.microsoft.com/en-us/library/ms186778.aspx

Once we have the data we need, we start to process it and it’s not that straightforward but its easy all you need to do is to gather information whether a column or field is nullable so that we can declare it as nullabe in the codes.  We also need a mapping to SQL DataTypes to .Net Data Types hence the big if conditions.

Also since we are using the S#arp Architecture there is a convention for PrimaryKeys so we don’t need to declare it as it is handled by the PrimaryKeyConvention class under NHibernateMaps\Convention, so if you named your PK right prefixing them with Id then this will be easy but you can always override it if you wanted to.  Below is the code that handles it

namespace CI5.Infrastructure.NHibernateMaps.Conventions
{
    #region Using Directives

    using FluentNHibernate.Conventions;

    #endregion

    public class PrimaryKeyConvention : IIdConvention
    {
        public void Apply(FluentNHibernate.Conventions.Instances.IIdentityInstance instance)
        {
            instance.Column(instance.EntityType.Name + "Id");
        }
    }
}

Finally we need to take note of Foreign Keys and what table is it related to as we don’t declare Id’s in the Entities but the class it is related to, hence we have this line.

if (sConstraintType == "FOREIGN KEY")
{
    oCSFile.WriteLine("\t\tpublic virtual " + sReferringTable + " " + sReferringTable + " { get; set; }");
}

Other than that everything should be straightforward.

The above code is made to generate only basic stuff so if you have added validation and other lines in your entities do not use it, otherwise I hope this would make someones life easier.

TOGAF ADM Phases

This might be the last time I will post something regarding TOGAF as I will be changing job functions soon and moving towards Data and Systems Integration.  This is one of the last slides I had presented in our office for those who wants to learn Enterprise Architecture in our organization that includes me as well, most of the material that I presented regarding TOGAF was derieved from the site OpenGroup as well as the book we had brought from them when we started EA on our organization.  This presentation is all about ADM Phases their definition and objectives.

To give you an overview here are the ADM Phases:

Preliminary
Phase A: Architecture Vision
Phase B: Business Architecture
Phase C: Information Systems Architecture
Phase D: Technology Architecture
Phase E: Opportunities and Solution
Phase F: Migration Planning
Phase G: Implementation Governance
Phase H: Architecture Change Management
Requirements Management

As I am coming from a Software Development Background I always see the model as similar to the Phases on SDLC but only have different names and functions but on experience acts the same specially the iterative software development models.  To have a bit of detail on what I am referring to here are the slides.

Architecture Development Method (ADM)

Just hot out of the presentation.
I just had presented the TOGAF Architecture Development Method with the Development Team and here is how it goes. Basically Architecture Development Method or ADM as defined in Wikipedia

The Architecture Development Method (ADM) is applied to develop an enterprise architecture which will meet the business and information technology needs of an organization. It may be tailored to the organization’s needs and is then employed to manage the execution of architecture planning activities.
The process is iterative and cyclic. Each step checks with Requirements. Phase C involves some combination of both Data Architecture and Applications Architecture. Additional clarity can be added between steps B and C in order to provide a complete information architecture.
Performance engineering working practices are applied to the Requirements phase, and to the Business Architecture, Information System Architecture, and Technology architecture phases. Within Information System Architecture, it is applied to both the Data Architecture and Application Architecture.

This means its the method to follow when you are developing an architecture it is similar to Software Development Life Cycle which is a set of methodologies in developing your software and these methodologies form the framework for planning and controlling the creation of an Software or System.  One thing to make note of is that ADM is so flexible that you can adapt it in any scenarios you might have, you can change the order or even omit one, you can do it iteratively the whose cycle or as a part. To give you more information here is the slides I presented.

Presenting TOGAF

Today I had presented TOGAF Enterprise Architecture Framework to our Technical Team, it will be a good introduction for them to understand Enterprise Architecture better as we are now implementing Architecture throughout our organization.

So why do Enterprise Architecture? A lot of reasons one is having a very efficient IT Operation, imagine you need something changed in your application lets say a field on a database table what would be the best way to know what applications will be affected by the change? Normally you just refer to people who know the application or if lucky you read through a good 100 page documentation. With EA combined with proper tools like Troux Architect its just a click of a mouse and magic you see all the dependencies (yeah you have t start creating relationships first and populate the repository either manual or automated).

Like this

Troux Architect

Another good reason will be reduced risk on future investments and better return on existing investment, faster cheaper and simpler procurement, the list goes on and on.  So to prevent lengthening this post here is the gallery of the slide show I presented.

Follow

Get every new post delivered to your Inbox.

Join 773 other followers