From a software clients' perspective, a good software service will exhibit the following characteristics:
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.
29.11.08
Why the Repository Pattern Sir?
When applying domain driven design, the repository pattern yields the following benefits:
* 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.
* 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
1. Grid- Does what it says on the tin. Provides row/column layout. Most versatile. Layout of choice for WPF window. Sizing supported via 3 strategies:
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.
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
The problem was how to group a number of radio buttons in a XAML UI. The solution was:
<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
Connecting the Netra 1s to a desktop x86 machine running window XP is proving to be a hard problem. The connection is via a custom built RS232/RJ45 female cable. This connects to the Netra 1's Serial A port. The sun server does not have any OS installed and no media drive, which leaves the null modem option as the only remote management solution. Constrained budgets mean that no extra accessories can be bought to fix the issue.
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.
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
We used the repository pattern(DomainDrivenDesign) to implement an injectable repository type in the peristence controllers in our ASP.NET MVC application.
The PersistenceFactory was introduced to decouple the concrete types created from the actual client using the type.
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
This chain of resposibility is from a system that handles a variety of reporting requests. The inheriting handlers are Russian dolled(each handler knows its successor).
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
Extension methods are a new language construct that allow the addition of new method definitions to an existing type.
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.
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.
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
As part of the continued journey in exploring the corners of software development, I decided to implement a new IDb4ObjectsRepository to handle persistence via an OODBMS. After an hour of hacking, I had an ASP.NET MVC application conversing with an object database.
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.
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?
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
This is going to be massive. It takes the "software as a service" paradigm to the next level. Let somebody else handle the messy infrastructure details and enable the developer/ISV to maximise value.
We see ourselves using the cloud commputing approach in our prototyping endeavours.
We see ourselves using the cloud commputing approach in our prototyping endeavours.
14.11.08
ASP.NET MVC. I love dumb models
I have seen and worked with various implementations of the MVC pattern. These range from the classic observer pattern implementation where the model has a reference to views/controllers that are interested in its state changes to independent standalone models that are view and controller agnostic. The ASP.NET MVC framework follows the latter approach.
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.
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#
This solution resolved my SQLite connection string configuration. The code makes use of the SQLiteConnectionStringBuilder class. The database filepath is shown here, but must reside in a configuration file for easy management.
get
{
string dbFilePath = @"C:\Program Files\SQLLite\TimesheetManager.db";
SQLiteConnectionStringBuilder bldr = new SQLiteConnectionStringBuilder();
bldr.DataSource = dbFilePath;
return bldr.ConnectionString;
}
Interacting with SQLite.NET API
A typical db session using SQLite.NET is shown below. The interaction idioms are similar to the ADO.NET API and this makes direct knowledge application from ADO.NET to SQLite.NET trivial.
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
Bought the Google Android G1 device. It's a solid, chunky and man-sized gadget. I am now developing an Android based application to investigate how easy development for this platform is. Enter SQLite, Eclipse and Xerial.
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.
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.
Subscribe to:
Posts (Atom)