OR mapping ,regardless of the mechanics employed, shifts the weight of enterprise software development from thinking about persistence to actually cogitating the problem space. I am now forced to think long and hard about the best aggregation or composition approaches for each of my domain objects. And this is precisely what my customer is paying me for. As Ayende says, “persistence is a solved problem”.
31.12.08
30.12.08
Mapping Subclasses in NHibernate
ContactTest.TestAddContactNotes : Failed
NHibernate.MappingException: No discriminator found for Zainco.YCW.Components.Domain.ContactNote. Discriminator is needed when 'single-table-per-hierarchy' is used and a class has subclasses
at NHibernate.Mapping.SingleTableSubclass.Validate(IMapping mapping)
at NHibernate.Cfg.Configuration.Validate()
at NHibernate.Cfg.Configuration.BuildSessionFactory()
at Zainco.YCW.Components.Utils.NHibernateHelper.get_Session() in NHibernateHelper.cs:line 13
at Zainco.YCW.Tests.ContactTest.TestAddContactNotes() in ContactTest.cs:line 94
This was due to an incorrect mapping strategy. Instead of using the table per hierarchy strategy, I resorted to using the table per subclass mapping strategy. The base table, Note, contains the elements common to my subclasses and the ContactNote maintains the association between the contact and the Note. I have a variety of Notes in the system(CommunityNotes, ParishNotes etc).
The mapping file for this strategy is:
<class name="Note" table="Note">
<id name="Id" column="Id">
<generator class="native"/>
</id>
<property name="Content"/>
<property name="DatePublished"/>
<joined-subclass name="ContactNote" table="ContactNote">
<key column="NoteId"/>
<many-to-one class="Contact" column="ContactId" name="Contact"/>
</joined-subclass>
</class>
20.12.08
Refactoring to DetachedNameQuery
IRepository repository = new NHibernateRepository();
IDetachedQuery query = new DetachedNamedQuery("GetMaxTaskId");
ITask task = repository.Find<Task>(query);
GetMaxTaskId is defined in my NHibernate mapping file, Task.hbm.xml.
The entry takes the following form:
<query name ="GetMaxTaskId">
<![CDATA[
select max(task.Id) from Task task
]]>
</query>
This really does feel good, especially when you type like I do
contrast with the old way of doing things
ITask task = TaskFactory.Instance;
task.Description = "Yak Shaving";
task.IsCompleted = false;
.
.
It's the small things like this that make for a more productive coding experience. The intent is more direct and one quickly gets to the destination in a DRY way. Nice!
NHibernate.LazyInitializationException: failed to lazily initialize a collection, no session or session was closed
Clients do not directly interact with the session.
So I use the IDetachedQuery interface to hold my queries like soz:
IDetachedQuery query = new DetachedQuery("...");
ITask task = repository.Find <Task>(query);
My task has a collection of categories which I am attempting to clear, but the session with which this collection is associated has already been disposed, so looks like I am going to have to force the collection to initialise before I return from the find method. The other option is to eagerly load the stuff i.e. set lazy loading to false.
As in Hibernate non-lazy loading is the default for loading collections in NHibernate. The solution to this problem was a case of setting the lazy attribute to false like this:
<set name="Categories" table="TaskCategory" lazy="false" cascade="all">
NHibernate can also be forced to initialize the collection by calling NHibernateUtil.Initialize(myObject) before the session is disposed.
18.12.08
Perhaps NHibernate Mapping attributes are poisonous
The result is a domain model that's very NHibernate aware, I cannot reuse the model without there being a whiff of NHibernate. This being the case, I have decided that xml mapping files are probably the way forward. I am aware of other mapping approaches, but perhaps, the verbosity and loosely coupled approach of mapping files has its advantages.
Yes attributes and mapping approaches use a declarative style, but one can not help feeling that embedding persitence crosscutting concerns in domain model could cause grief further down. Mapping files, you have a new friend.
9.12.08
An NHibernate Helper for working with the NHibernate.Mapping.Attributes API
This will requires configuration information to be placed in an app.config file as documented in the NHibernate documentation. One is then required to have a single well known location from where to obtain an instance of the ISession(think PersistenceManager) type. The code below shows how to configure the serializer and return an ISession:
using System.IO;
using System.Reflection;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Mapping.Attributes;
namespace Zainco.YCW.Components.Utils
{
public sealed class NHibernateHelper
{
private static ISession _session;
public static ISession Session
{
get
{
if (_session == null)
using (MemoryStream stream = new MemoryStream())
{
HbmSerializer.Default.Validate = true;
HbmSerializer.Default.HbmNamespace = "Zainco.YCW.Components.Domain";
HbmSerializer.Default.HbmAssembly = "Zainco.YCW.Components";
HbmSerializer.Default.Serialize(stream, Assembly.GetExecutingAssembly());
stream.Position = 0;
Configuration cfg = new Configuration();
cfg.Configure();
cfg.AddInputStream(stream);
_session = cfg.Configure().BuildSessionFactory().OpenSession();
}
return _session;
}
}
}
}
System.Data.SqlClient.SqlException: Invalid object name 'hibernate_unique_key' when using SQL Server 2005
the actual code that causes this is:
session.Save(contact);
The Id attribute on the contact entity is configured as:
[Id(Name = "Id", Type = "int")]
[Generator(Class = "hilo")]
public virtual int Id
ContactTest.TestAddContact : FailedSystem.Data.SqlClient.SqlException: Invalid object name 'hibernate_unique_key'.
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
at System.Data.SqlClient.SqlDataReader.ConsumeMetaData()
at System.Data.SqlClient.SqlDataReader.get_MetaData()
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader()
at NHibernate.Id.TableGenerator.Generate(ISessionImplementor session, Object obj)
at NHibernate.Id.TableHiLoGenerator.Generate(ISessionImplementor session, Object obj)
at NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(Object entity, String entityName, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.FireSave(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.Save(Object obj)
at Tests.ContactTest.TestAddContact() in ContactTest.cs:line 20
The solution is to use the native option, this picks identity, sequence, hilo depending on the capabilities of the underlying RDBMS.
[Id(Name = "Id", Type = "int")]
[Generator(Class = "native")]
public virtual int Id
{
4.12.08
Permission error when trying to open a new database connection from an XBAP
{"Request for the permission of type 'System.Data.SqlClient.SqlClientPermission, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed."} System.Exception {System.Security.SecurityException}
This is because the default security mode for an XBAP is partial trust. The XBAP is sandboxed and has restricted permissions to the file system, database etc. The .NET Framework uses code access security to limit what the XBAP can do. This is kind of consistent with the Flash, Java applets paradigm that XBAP tries to emulate.
It is tempting to assign the application trust via the following mechanism:
In VS2008, do the following:
Double click the VS projects' Properties node containing the XBAP-> Select Properties->Choose the security tab-> Select the option which says "This is a full trust application"->
However this Full Trust permissioning has potential drawbacks that require unpalatable workarounds.
The side effect of the change is that me XBAP can not now be run from a virtual directory or website.
This leaves me to wonder. Is what I need an XBAP, SilverLight application, a standalone XAML application or God forbid an ASP.NET app?
I still want the rich internet application experience and I still want to have a centralised web-like configuration management model. The last thing I want is to be touching each clients' machine to tweak a setting here and a setting there. Because this approach inevitably ends in tears.
I also do not want to implement orthogonal constructs that check for permissions and end up littering the codebase with try/catch blocks that test for permissions.
So in the end after careful consideration of my problem context, SilverLight is the way to go.
A unit testing framework in Turbo Pascal
The main point of this exercise is to implement an xUnit testing framework using Pascal. This follows on from a segment in Kent Becks' book, Test Driven Development, in which Mr. Beck implements an xUnit framework in python.
TODO add code here.
Type registry and the Factory Method
public class Creator
{
:
public static IVehicle Create(VehicleType vehicleType)
{
IVehicle vehicle = new Chisasa();
if(VehicleType.Sedan)
vehicle = new Sedan();
if(VehicleType.FourByFour)
vehicle = new FourByFour();
return vehicle;
}
}
This decision structure is easily refactored to an in-memory type registry which uses the lookup metaphor as demonstrated below:
private IDictionary<VehicleType,IVehicle> Vehicles
{
get
{
IDictionary<VehicleType,IVehicle> vehicles = new Dictionary<VehicleType,IVehicle>();
vehicles.Add(Vehicle.Sedan, new Sedan());
vehicles.Add(Vehicle.Mazembe, new Mazembe());
vehicles.Add(Vehicle.Chisasa, new Chisasa());
vehicles.Add(Vehicle.Chimbayambaya, new Chimbayambaya());
return vehicles;
}
}
public static IVehicle Find(VehicleType vehicleType)
{
return Vehicles[vehicleType];
}
If you are observant, you will notice that this changes the semantics of the implementation. We have now moved from creating objects to finding objects in a registry. Sound familiar? This emergent design shows us that the Factory Method is really a respository pattern in disguise. Refactoring a GOF pattern has teleported us to one of the basic tenets of Domain Driven Design, the Repository Pattern.
Some considerations to take into account would be deciding the best collection to use
to reduce the cost of lookup. It could also be possible to externalise the registry depending on the nature of the problem space.
29.11.08
The characteristics of a good software service
1. Simple to use. You ask it for stuff and it gives you back precisely what you want. If there are any failures, these are reported. The service should fail fast. No slow insidious failures should be allowed.
2. The chunkiness or chattiness of the API should take into account the useage context. The cost of remote invocation should be factored into the design. In a distributed enviroment it might be worth measuring the cost of providing a chunky API vs a chatty interface.
3. The service should expose an interface for metadata and other out-of-band information.
4. The service should be interoperable - dont tie the service to platform specific return types unless the requirement explicitly states so or there is a compelling performance reason to do so. This assumes that you have measured the benefits of doing so.
From an implementation perspective it is desirable that the service exhibit the following attributes:
1. Statelessness - an invocation of the service at time t + 1 should be independent of the invocation at time t. The services' invocation history is not important. The "now" is more important than what has gone before.
2. Operations should be defined interms of concepts in the domain. Parameters and return values should be defined interms of domain objects. Beware of primitive obsession, i.e passing strings, int, floats etc when you should really be returning well encapsulated objects or passing parameter objects.
Why the Repository Pattern Sir?
* Represents all objects of a certain type as a conceptual set
* Provides access to roots of aggregates
* Can return summary information
* Provides mechanism for object add/delete
* Encapsualates DB access technology and strategy
* Answers the question, "How do I get a handle to an object" - done via object traversal, direct query execution to find object
* Clients of the repository interface use query based methods to get objects
* Repository is a first class client to object factories. The repository interface can encapsulate factories.
* Simplifies mock testing
Interface based repository implementations promote substitutability which is a naturally results in highly configurable and loosely coupled software architectures as in Liskov Substitution.
When to use specific WPF layouts
a) Absolute size - allows exact sizing via device-independent units. Inflexible and does not support changing content size, changing container size or localization.
b) Proportional size - Space divided between a group of rows and columns
<ColumnDefinition Width="*"></ColumnDefinition>
This syntax is very similar to frames
c) Automatic size - A versatile sizing mode; Row/Column allocated exact space it needs and no more.
<ColumnDefinition Width="Auto"></ColumnDefinition>
Mixing Grid Sizing Strategies
When mixing proportional sizing with other sizing modes, the proportionally sized rows or columns get the remaining space.
<strong>Assigning weights</strong>
<RowDefinition Height="2*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
Means make the height of the row above twice the height of the row below
2. Canvas
Allows the positioning of elements and controls using precise coordinates. This is ideal for a drawing application, but a sub-optimal solution for rich dynamic GUIs. The layout is fairly lightweight because it does not include complex layout for position and sizing controls and elements. It is essentially the WYSIWYG of the WPF layout world.
Example of a canvas layout:
<Canvas>
<TextBox Canvas.Left="100" Canvas.Top="50"> Is positioned at (100,50)</TextBox>
</Canvas>
3. InkCanvas - the main aim of this layout is for stylus input. Think tablet PCs and mouse interactivity. Users can annotate content using strokes.
4. UniformGrid - a highly constrained and inflexible layout system. It does not support predefined columns and rows. The Rows and Columns are defined as attributes on the UniformGrid element. Cells are allocated the same size. Elements are rendered in the grid based on the order in which they are defined.
<UniformGrid Rows="2" Columns="2">
<Button>1</Button>
<Button>2</Button>
<Button>3</Button>
<Button>4</Button>
<UniformGrid>
This layout could be useful in a board game for example Nsolo.
26.11.08
Grouping RadioButtons using the StackPanel element
<StackPanel Name="magazineList" Grid.Column="1" Grid.Row="0" Grid.ColumnSpan=">
<RadioButton>By email</RadioButton>
<RadioButton>By mail</RadioButton>
<RadioButton>No magazine</RadioButton>
</StackPanel>
An alternative approach would be to use a named group descriptor.
The dark art of Netra t1 105, x86 and custom RS232/RJ45 interconnects
Alternative approaches are:
1. Re-purpose the RJ45/USB Connector to provide the linkage between the two devices.
2. Ask for more cash to buy SUN compatible hardware which is compatible with the problem domain.
3. Scrap the project - easy to do but not a realistic option.
15.11.08
IoC in ASP.NET MVC
HandleError(View = "AddItemError",ExceptionType=typeof(CreateItemException))]
public class PersistenceController:Controller
{
private readonly IPersistenceManager _persistenceManager;
public PersistenceController(IPersistenceManager persistenceManager)
{
_persistenceManager = persistenceManager;
}
public PersistenceController():this(PersistenceFactory.CreateInstance())
{
}
The PersistenceFactory was introduced to decouple the concrete types created from the actual client using the type.
Chain of responsibility
namespace Components.Reports.QueryHandlers
{
public abstract class ReportQueryHandler
{
protected ReportQueryHandler _reportHandlerSuccessor;
protected ReportType _reportRequest;
public ReportQueryHandler(ReportType reportType)
{
_reportRequest = reportType;
}
protected string LoadQuery(string queryFilePath)
{
if (!string.IsNullOrEmpty(queryFilePath))
return File.ReadAllText(queryFilePath);
else
throw new ArgumentNullException(queryFilePath);
}
public virtual void HandleReportRequest()
{
if (_reportHandlerSuccessor != null)
_reportHandlerSuccessor.HandleReportRequest();
}
}
}
In search of dynamic cohesion via extension methods
One particular scenario where they have proved useful is in extending the HtmlHelper type that allows rendering of controls in ASP.NET MVC. This encourages a belated type of cohesion, i.e., all concerns to do with control rendering in the view must reside in the HtmlHelper.
public static string CommandBuilder(this HtmlHelper helper, string controller, string action, string commandName, int id)
{
return string.Format("<a href='/{0}/{1}/{2}'>{3}</a>", controller, action, id, commandName);
}
However one wonders whether the same could not be achieved through normal type inheritance. If there are breaking changes in the implementation from Microsoft, then be prepared to break.
Object Persistence without the impedance mismatch
There were no schemas, mapping layers, sql queries or setup scripts to fiddle with.
The only problem I seemed to encounter was that of binding my object collections to drop down lists that were expecting an id for each bound object. Db4objects does not have great support for generating sequences numbers for objects being persisted.
There is an internal representation of the object id, but this requires groping into the guts of the api to retrieve it. Perhaps what's required is some interfaces e.g. ISequenceGenerator which can be implemented by entity objects requiring an id. Value objects by their very definition would not need to implement this interface.
private void AddItem(T entityToStore) where T:IEntity
{
using(IObjectContainer db = Db4oFactory.OpenFile(Db4oService.FilePath))
{
db.Set(entityToStore);
}
}
The sheer ease with which I was able to integrate Db4Objects left me a bit uneasy. Can object persistence be so easy? Why are object databases not prevalent?
Azure Platform Services
We see ourselves using the cloud commputing approach in our prototyping endeavours.
14.11.08
ASP.NET MVC. I love dumb models
This makes solutions implemented using this approach ammenable to the repository pattern(DomainDrivenDesign). The model is pure in intent and does not care about non-model related concepts. The attendant benefit of such an approach is that models can be injected into the controller via IoC techniques.
3.11.08
Using the SQLiteConnectionStringBuilder in C#
get
{
string dbFilePath = @"C:\Program Files\SQLLite\TimesheetManager.db";
SQLiteConnectionStringBuilder bldr = new SQLiteConnectionStringBuilder();
bldr.DataSource = dbFilePath;
return bldr.ConnectionString;
}
Interacting with SQLite.NET API
int retCode;
using (SQLiteConnection connection = new SQLiteConnection(ConnectionString))
{
connection.Open();
using (SQLiteTransaction transaction = connection.BeginTransaction())
{
using (SQLiteCommand cmd = new SQLiteCommand(commandText, connection))
{
retCode = cmd.ExecuteNonQuery();
}
transaction.Commit();
}
} return (retCode > 0 ? true : false);
Attaching Databases in SQLite
sqlite> ATTACH DATABASE "C:\Program Files\SQLLite\TimesheetManager.db" AS TimeSheetManager;
sqlite> .databases
seq name file
--- --------------- ----------------------------------------------------------
0 main
2 TimeSheetManager C:\Program Files\SQLLite\TimesheetManager.db
sqlite>
SQLite, Android and Curly braces
SQLite happens to have the largest deployment base of any database. Read the stats and weep. It is ideal as an embedded database, which is what I need for this project. So forget about stored procedures, evil platform/licensing constraints and redundant complexity. This sofware just works.
There are beautiful and easy to user JDBC compliant wrappers which should make the database integration simpler. The Android Eclipse PlugIn should make development a breeze.
31.10.08
OpenDX and XMing on Windows XP
Download the OpenDX binaries
You will need to run the XServer before launching OpenDX. Once launched, run through the OpenDX samples.
27.10.08
The Mediator pattern via an event subscription mechanism
TODO
16.9.08
10.9.08
Choice of head node
The criteria that settled the matter was as follows:
1. Head node must have similar software/hardware mix as the slave nodes. This makes the management and configuration of the cluster less problematic. Configuration will be managed using the Sun JumpStart utility. This allows centralised node management and homogenisation of the slave nodes.
2. Cost
3. Performance
4. Media enabled
27.8.08
Zainco Beowulf
The goals of the R&D project are:
1. To determine the applicability of parallelization to problems in Computational Finance
2. To evaluate various implementations of the Message Passing Interface
3. To explore the issues inherent in high frequency data visualisation
4. To harness the .NET parallelisation APIs
5. To have fun whilst I do all the above
One of these cuties looks like this-
I have £675.00 left to spend and this should buy the following hardware components:
1. 8-12U server cabinet,
2. 12 port networking switches,
3. Cabling CAT 5e 10/100
These T105's babies will be running the Open Solaris OS, SUN Grid Engine and the various MPI implementations currently available. I don't intend to spend a single penny on software apart from the bandwidth consumption costs incurred in downloading.
26.8.08
Internal Rate of Return(IRR) Using Newton-Raphson in C#
I am an ardent advocate of software reuse, but when faced with APIs that are not extensible, the options are: Google for an alternative implementation; build a custom component or defenestration.
I explored the first option, but the solutions available did not integrate with the clients' target platform. A webservices facade was not an option either - think technical debt and the "my Java is better than your Java" type arguments. I am saving the more drastic option for an apt occasion.
The IRR function is essentially a polynomial function in r whose solution is any value of r that makes the function equal to zero. A more detailed description is available here.
Formally IRR can be expressed as:
An expanded form of this is expressed as:
There are several approaches to solving polynomials for zero roots and in the majority of cases, the limiting factors tend to be speed of convergence, accuracy of approach and the number of compute cycles incurred.
The business needs to get the answer today and it must be reliably and accurately produced on the hardware available.
The Newton-Raphson method of root finding is used. Other approaches e.g. Bisection where prototyped, but proved less robust in UAT.
The roots of a polynomial function can be approximated by the following equation:
The initial guess is derived by linearising the IRR function. Linearisation simply means getting rid of the higher order terms. The linearised version of the function thus becomes:
The source code for the IRR calculator implementation is here.