Moving on...
0 comments Published Jun 12, 2012 by Miroslav Popovic inTo anyone interested, I have decided to move my blog to my own domain and change the blogging platform. My new blog is now based on FunnelWeb and the address is: http://blog.miroslavpopovic.com.
Also, there is a new feed for it, so please redirect your feed readers to it: http://feeds.feedburner.com/miroslavpopovic/blog.
Thanks!
Materials and links from my INETA talk on Thursday
0 comments Published Feb 18, 2011 by Miroslav Popovic inBelow are the links for downloading PowerPoint presentation and samples from my talk titled: Design Patterns for developing WPF, Silverlight and Windows Phone 7 applications; MVVM and Caliburn.Micro.
- MVVM and Caliburn.Micro presentation (The slides are on my native language)
- MVVM and Caliburn.Micro examples
Other links from the presentation:
- http://caliburnmicro.codeplex.com
- http://www.caliburnproject.org
- http://devlicio.us/blogs/rob_eisenberg - Rob Eisenberg’s blog
- http://live.visitmix.com/Archive – Archive of all video materials from MIX conference. Look for “Build your own MVVM Framework” from MIX 2010
- http://blogs.msdn.com/b/johngossman/archive/2005/10/08/478683.aspx – First publishing of MVVM
- http://martinfowler.com - Martin Fowler
- http://codebetter.com/jeremymiller - Jeremy Miller’s blog
- http://en.wikipedia.org/wiki/MVVM – contains links to all MVVM frameworks currently available
- http://delicious.com/miroslav.popovic/mvvm – My MVVM bookmarks tag
Hope I wasn’t too boring
New Silverlight blog
1 comments Published Feb 9, 2009 by Miroslav Popovic inMy good friend Radenko Zec started blogging about Silverlight. Considering he has won 3rd place on European Silverlight Challenge, he’ll surely have something to say about it.
Visit him at: http://blog.developers.ba/
Implement Firefox-like search in WPF application using M-V-VM
4 comments Published Feb 1, 2009 by Miroslav Popovic inI have just submitted my first CodeProject article. You can find it here.
Although I had several article ideas over the years, my laziness prevent me from posting them :)
Hopefully this one will come in handy for those learning and using M-V-VM.
A good deed
4 comments Published Oct 20, 2008 by Miroslav Popovic in agile, NHibernateLooks like I did a good deed today :)
And despite Stephen's words, I did it out of gratitude, not out of pity :)
Repository implementation
0 comments Published Oct 16, 2008 by Miroslav Popovic in DDD, NHibernateAlong with NHibernate mappings, Peniko.DataLayer project contains Repository implementations. Repository interfaces are in Peniko.Domain project, as mentioned before.
All communication with NHibernate is done through ISession instance. Session is basically a Unit of Work for NHibernate. We have a standard NHibernateHelper static class for encapsulating ISessionFactory and for creating / opening the session:
public static class NHibernateHelper
{
private static ISessionFactory _sessionFactory;
private static ISessionFactory SessionFactory
{
get
{
if (_sessionFactory == null)
{
var configuration = new Configuration();
configuration.Configure();
configuration.AddAssembly(typeof(Product).Assembly);
_sessionFactory = configuration.BuildSessionFactory();
}
return _sessionFactory;
}
}
public static ISession OpenSession()
{
return SessionFactory.OpenSession();
}
}
SessionFactory is created from the NHibernate configuration the first time its accessed. Configuration comes from hibernate.cfg.xml file defined in UI and test projects:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<property name="connection.connection_string">...</property>
<property name="show_sql">true</property>
<mapping assembly="Peniko.DataLayer" />
</session-factory>
</hibernate-configuration>
In Peniko.DataLayer, every Repository method uses its own session, so we can't use NHibernate's lazy loading feature. Better option would be session-per-conversation pattern mentioned here, but we'll leave it as is for now.
The most important class in Repository implementation is Repository<T> implementing our IRepository<T> interface:
public interface IRepository<T> where T : Entity<T>
{
void Save(T entity);
void Delete(T entity);
T GetById(Guid id);
IList<T> GetAll();
}
public abstract class Repository<T> : IRepository<T> where T : Entity<T>
{
private static readonly ILog _log = LogManager.GetLogger(typeof (Repository<T>));
protected static ILog Log { get { return _log; } }
public void Save(T entity) { ... }
public void Delete(T entity) { ... }
public T GetById(Guid id) { ... }
public IList<T> GetAll() { ... }
}
It's defined as abstract class and provides inherited classes with basic strongly typed methods for saving, deleting and retrieving all entities or a single entity by id and also an log4net's ILog instance . Inherited class is defined like this:
public class ProductRepository : Repository<Product>, IProductRepository { ... }
This is a Save method from Repository<T>:
public void Save(T entity)
{
if (!entity.IsValid) throw new ValidationException("Entity is invalid");
using (var session = NHibernateHelper.OpenSession())
using (var transaction = session.BeginTransaction())
{
Log.DebugFormat("Saving entity Id: {0}", entity.Id);
try
{
session.SaveOrUpdate(entity);
AfterSaveEntity(session, entity);
transaction.Commit();
}
catch (StaleObjectStateException ex)
{
transaction.Rollback();
Log.Error("Error saving entity", ex);
throw new ConcurrencyException("The data has been modified by another user", ex);
}
catch (HibernateException ex)
{
transaction.Rollback();
Log.Error("Error saving entity", ex);
throw;
}
}
}
First thing it does is to check if entity is valid. Then it opens a session and begins a new transaction on it. As of NHibernate 2.0, all Saves, Updates and Deletes must be encapsulated in transaction. Save method calls session.SaveOrUpdate() which does both insert and update operations based on the value of entity.Id. In our case, if Id is Guid.Empty, it will do Insert, otherwise Update.
AfterSaveEntity call allows inherited class to do some action after the entity is saved successfully. I.e. to save some other, unrelated entity.
Note that we catch StaleObjectStateException. That exception is thrown when there is a concurrency problem. We encapsulate it in our ConcurrencyException and throw that instead. That way it's easy to catch it in UI code without dependency on NHibernate.
Delete method is more or less the same. The only difference is that it calls session.Delete() instead of session.SaveOrUpdate().
GetById looks like this:
public T GetById(Guid id)
{
using (var session = NHibernateHelper.OpenSession())
{
Log.DebugFormat("Getting entities with Id: {0}", id);
try
{
var entity = session.Get<T>(id);
AfterGetEntity(session, entity);
return entity;
}
catch (HibernateException ex)
{
Log.Error("Error getting entities by id", ex);
throw;
}
}
}
This method is very simple. session.Get<T>(id) returns a single entity with the given id. GetAll method is similar, but it uses NHibernate Criteria API and returns session.CreateCriteria(typeof (T)).List<T>() as a result.
In another project I'm currently involved, Repository also has FindAll and FindOne methods that accept DetachedCriteria as a parameter. The idea came from 12. episode of Summer of NHibernate.
Other Repository classes inherited from Repository<T> have its own methods for retrieving entities. These methods are mostly using Criteria API. More on Criteria API and HQL in NHibernate learning material.
Mapping entities with NHibernate
6 comments Published by Miroslav Popovic in NHibernateThe next thing to be done was NHibernate mapping. Mappings are defined in Peniko.DataLayer project.
Every entity class has its own mapping file. Mapping file is named after a class, so if class name is Category, the mapping file is Category.hbm.xml. hbm stands for Hibernate mapping. Having this naming scheme is not required, but NHibernate will try to look for these names automatically when mapping. If you want to name your mappings differently, then you'll need to tell that to NHibernate.
Mapping file must have Embedded Resource build action. That's the thing that gets easily forgotten, so double check all your mapping files.
Writing a mapping file can be tedious and error-prone, but there is a cure for that. NHibernate comes with two XML schema files (nhibernate-configuration.xsd and nhibernate-mapping.xsd) that you can copy to Program Files\Microsoft Visual Studio 9.0\Xml\Schemas. Once there, they'll provide you with Intelli-sense when writing NHibernate mappings and configuration in Visual Studio.
If you are ReSharper user, there is also a nice ReSharper NHibernate plugin. It checks type, assembly and property names and allows navigation to mapped classes with Ctrl+Click on class or property name. Also, any renames are reflected in mapping file.
Below is an example of a very simple mapping:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="Peniko.Domain"
namespace="BLDotNet.Peniko.Domain">
<class name="Category" table="Categories">
<id name="Id" column="CategoryId">
<generator class="guid" />
</id>
<property name="Name" column="Name" length="50" not-null="true" unique="true" />
</class>
</hibernate-mapping>
You must fully qualify type names in mapping files ("Namespace.Class, Assembly"), or you can define assembly and namespace attributes on root tag.
If the table name differs from the class name, there has to be a table attribute on <class> tag. In our case, all table names are plural.
id must be defined for all mapped classes. There are different id generators in NHibernate, but you'll most likely choose between "guid" and "native". When "native" generator is selected, NHibernate will use database generated value - this is an identity field in SQL Server. NHibernate maintains ids itself, so you don't have to ever assign values to them (unless you are using "assigned" generator).
All simple properties are mapped with <property> tag. There are also <many-to-one>, <one-to-one> and <one-to-many> tags for relations with other mapped classes; <subclass> and <joined-subclass> for inheritance mapping; <map>, <set>, <list> and <bag> for collection mapping and even more tags.
This should be enough to get you started with NHibernate mapping. For more details see NHibernate learning material.
Unit Testing the Domain
0 comments Published by Miroslav Popovic in unit testingThis post is a follow-up to Are you valid?. Last time I tried to explain how the validation is done in our Domain project.
Peniko.Domain.Tests project contains Unit Tests for our Entity classes. The tests are written using NUnit library. Every entity class has its own test fixture. Below is a sample fixture for Category entity:
namespace BLDotNet.Peniko.Domain.Tests
{
[TestFixture]
public class CategoryFixture
{
private const int NameMaxLength = 50;
private Category _category;
[SetUp]
public void SetUp()
{
_category = TestGlobals.GetValidCategory();
}
[Test]
public void CanCreateCategory()
{
Assert.IsTrue(_category.IsValid);
Assert.AreEqual("NewCategory", _category.Name);
}
[Test]
public void CannotHaveNullName()
{
_category.Name = null;
Assert.IsFalse(_category.IsValid);
}
[Test]
public void CannotHaveEmptyName()
{
_category.Name = String.Empty;
Assert.IsFalse(_category.IsValid);
}
[Test]
public void CanHaveMaxLengthName()
{
_category.Name = new String('A', NameMaxLength);
Assert.IsTrue(_category.IsValid);
}
[Test]
public void CannotHaveTooBigName()
{
_category.Name = new String('A', NameMaxLength + 1);
Assert.IsFalse(_category.IsValid);
}
}
}
And here is how the Category class looks like:
namespace BLDotNet.Peniko.Domain
{
public class Category : Entity<Category>
{
[NotNullValidator]
[StringLengthValidator(1, 50,
MessageTemplateResourceName = "CategoryNameLength",
MessageTemplateResourceType = typeof (Category))]
public virtual string Name { get; set; }
}
}
This case is very simple. Category has only one property - Name, apart from Id inherited from Entity class. The fixture only tests if the Category object can be created and if the validation is OK. Name property is tested for null and upper and lower length boundaries.
You'll notice that there is a SetUp() method that uses TestGlobals.GetValidCategory() method to create the Category to test. TestGlobals is a static class containing methods to create valid entities. We extracted entity creation from our test classes so we can reuse some entities as properties of other entities.
I.e. Project object has a Category property. TestGlobals.GetValidProject() calls TestGlobals.GetValidCategory() to assign to Category property. Some of you may ask now: Hey, what about mocking? Shouldn't you assign the mock Category to Project? Well, we are going one step at a time, no mocking frameworks learned yet :)
Most of our Domain tests looks like this. Some of the classes like OutputInvoiceDetail and InputInvoiceDetail have encapsulated calculations, so their tests are little more complicated, but not worth mentioning.
There are no Repository tests in Peniko.Domain.Tests project. Repositories are tested in separated DataLayer.Tests project. More on that later.
You are an idiot!
0 comments Published Oct 6, 2008 by Miroslav Popovic in agile, ALT.NETI just had an interesting conversation with a friend of mine. He recently started to learn NHibernate, in fact we are working together on one application.
Apparently, he got into an argument with his co-worker about NHibernate and O/RM in general. The co-worker of his is an experienced developer, the kind of people whose advice you would appreciate. And he had an advice. Don't use O/RM! It's slow, unnecessary complication which favors Java style of architecture. Oh, and it's extremely hard for debugging and maintenance! He used an O/RM in ONE project, and it's bad. Let's all avoid it.
Needles to say, but these arguments made my friend feel bad. Was it a bad decision to start learning NHibernate and to use it in an application?
The title of this post is a little harsh, but whenever I have an argument like this I always feel that the other person is trying to say to me that I'm an idiot. "Yes, you are!", you might said, "Why should it bother you. Don't take it to the heart." Well, what can I say ... It does bother me, so let me have my own arguments here.
- It's slow - He's right. O/RM is slower than plain ADO.NET code. Several percents or tens of percents. Hell, it's another abstraction layer, it has to be. .NET Framework applications are slower than C++ ones, and C++ applications are slower than assembler ones. Does this mean that we should ditch .NET in favor of assembler? Maybe, for a tiny performance critical application or parts of code, but for an enterprise application...? The benefits of an O/RM outweighs the performance impact in most situations.
- Unnecessary complication - I shouldn't even comment this, because I'm not sure what he meant or how was his application structured. In most cases I encountered, the developers (myself included) were more responsible for complicated applications than frameworks or tools. We often start using something just after looking at Hello World sample. Don't get me wrong, this can work, we learn as we go, but we should take a time to at least find and learn best practices.
I still remember what came out of my first CSLA application. Boy, was it a mess.
Or my first relational database application. It should have stored daily entries with details, plain master-detail case. I remember creating a table per day in code (Entry_10_05_99, Entry_10_06_99...), so each day details had it's own table. The case for The Daily WTF. - Java style architecture - WTF?!? What's wrong with Java? I've never used it professionally, but still appreciate all ideas borrowed from it in .NET Framework and third-party libraries and tools.
- Hard for maintenance and debugging - Really? I wonder what O/RM has he been using. NHibernate uses log4net for logging and has option to log ALL generated SQL code. If that's not enough for you, it's Open Source, so you can attach the debugger to it and step thru the code if necessary.
Hard to maintain? Let me tell you about the big enterprise application I had worked on several years ago and still have to maintain it... We did some bad design decisions and end up with business code in both .NET application and SQL Server stored procedures. Whenever we have to change something we make a change in stored procedure, than in .NET application, then deploy it, fix bugs, etc. Those changes in two places are rather tedious. Not to mention we don't have stored procedures under source control for obvious reasons. In other, NHibernate powered application, we have to only refactor and deploy. All our code is in one place, and under source control. That's why I favor "stored procedure"-less databases lately.
And one more thing... Ever tried Unit / Integration Tests? You'll definitely have less bugs to cope with later on.
Final words. Don't let anyone kill your desire to learn new things just because he/she had tried it once and consider it bad. Try it for yourself, at least on a small test project. Learn more, don't limit yourself to one technology / framework / tool. Oh, and take your time to learn best practices :)
That's what ALT.NET tries to teach us.
Are you valid?
0 comments Published Aug 16, 2008 by Miroslav Popovic in VABThe next thing we wanted to implement to our Core project was a business object validation. There are several paths we could take:
- To use Enterprise Library's VAB (Validation Application Block)
- To use some other open source validation library
- To roll out our own validation and implement IDataErrorInfo interface for UI to use
Because we qualified this application as a learning project, and we haven't used VAB before, we decided to try it. VAB enables developers to attach validation rules to properties in declarative way, by using attributes. Rules can also be defined in config file, allowing the simple rules change after the application is deployed, but that wasn't a requirement for this project.
Most of our entity classes now have properties that look like this:
[NotNullValidator]
[StringLengthValidator(3, 15,
MessageTemplateResourceName = "ProductCodeLength",
MessageTemplateResourceType = typeof (Product))]
public virtual string Code { get; set; }
[NotNullValidator]
[StringLengthValidator(1, 50,
MessageTemplateResourceName = "ProductNameLength",
MessageTemplateResourceType = typeof (Product))]
public virtual string Name { get; set; }
In order to avoid cluttering of code with localized error messages, they are moved to project resources, hence the MessageTemplateResourceName and MessageTemplateResourceType arguments.
And now the big thing... In order to check the object validity, IsValid() method is added to Entity<T> class (base class for all our entity objects, defined as Entity<T> where T: Entity<T>). IsValid is calling VAB Validator to check the property values on the object and returns true if object is valid. The first version looked like this:
public virtual bool IsValid()
{
return Validation.Validate((T)this);
}
Validation class is a façade. It creates a Validator object and tests for validity in a single line of code. Validate method is actually generic - Validation.Validate<T>((T)this), but T argument is redundant.
The cast to type T was necessary, because the Validator isn't smart enough to go down the inheritance hierarchy. If we call Validate(this), it would try to find validation rules on the current class (Entity<T>), but not on inheriting classes. I.e. public class Product : Entity<Product>. By having a cast to T (Product in this case), we ensure that the rules are checked on the Product class.
This worked fine up until recently, when our entity model became more advanced:
public class Warehouse : Entity<Warehouse>
...
public class CommissionerWarehouse : Warehouse
...
IsValid method couldn't handle the CommissionerWarehouse class. The cast to T in Validate method gave it only a Warehouse type to check. CommissionerWarehouse rules were ignored. In order to handle this case, IsValid was rewritten to use the Validator object directly:
public virtual bool IsValid()
{
var entityValidator = ValidationFactory.CreateValidator(GetType());
return entityValidator.Validate(this).IsValid;
}
The code is twice as long as before, but I can live with it :)
The magic of this method allows easier Unit Testing (more on that later) and validation calls from the client without the reference to Validation Application Block assemblies. We could add some method to return error messages too, but that's not necessary, since we are using Martin Bennedik's WPF Integration for VAB.
Blog Archive
My Blog List
-
When Abstractions Break1 week ago
-
From Bugs to BEAM1 month ago
-
Native AOT libraries with TypeScript1 year ago
-
-
-
LLBLGen Pro v5.6 has been released!5 years ago
-
-
Cake Build Tool6 years ago
-
ASP.NET hosting with lifetime 50% off11 years ago
-
-
-
-
-