SlideShare a Scribd company logo
BusinessSolutions
SoftwareEngineering
24.02.2009  1
Foundations of Programming
Building Better Software
BusinessSolutions
SoftwareEngineering
24.02.2009  2
Foundations of Programming
Based on a free EBook from Karl Seguin
www.codebetter.com
BusinessSolutions
SoftwareEngineering
24.02.2009  3
Agenda
 ALT.NET
 Domain Driven Design
 Persistence
 Dependency Injection
 Unit Testing
 Object Relational Mappers
 Conclusion
BusinessSolutions
SoftwareEngineering
24.02.2009  4
ALT.NET
 The MSDN Way vs. ALT.NET
 Data centric versus Domain driven
 Goals: Maintainability
– > 50% in maintenance state
– iterative development  continuous changes
BusinessSolutions
SoftwareEngineering
24.02.2009  5
ALT.NET – Principles
 Simplicity
 YAGNI
 Last Responsible Moment
 DRY
 Explicitness and Cohesion
 Coupling
 Unit Tests and Continuous Integration
BusinessSolutions
SoftwareEngineering
24.02.2009  6
DOMAIN DRIVEN DESIGN
BusinessSolutions
SoftwareEngineering
24.02.2009  7
„What is Design? It’s where you stand with a foot in two
worlds – the world of technology and the world of people
and human purposes – and you try to bring the two
together.”
MITCHELL KAPOR
BusinessSolutions
SoftwareEngineering
24.02.2009  8
Data Driven Design
 How to design your system?
– Data-driven or domain-centric
 Build your system around the data
 Database first
 Then mimick in .NET
 Great MS tool support
BusinessSolutions
SoftwareEngineering
24.02.2009  9
Domain Driven Design (DDD)
 Focuses on the problem domain
 Data AND behaviour
 Tool  OOP
BusinessSolutions
SoftwareEngineering
24.02.2009  10
„In the past, I'd frequently get pissed off with clients.
They were annoying, didn't know what they wanted and
always made the wrong choice.
Once I actually thought about it though, I realized that I
wasn't nearly as smart as I thought I was. The client
knew far more about his or her business than I did. Not
only that, but it was their money and my job was to
make them get the most out of it.
As the relationship turned more collaborative and
positive, not only did the end result greatly improve, but
programming became fun again.”
KARL SEGUIN
BusinessSolutions
SoftwareEngineering
24.02.2009  11
Users, Clients and Stakeholders
 Client: pays the bill, should make decisions
about features and priorities, often User
 User: uses System, different types
 Stakeholders: anyone with a stake in the
system
 Domain experts
BusinessSolutions
SoftwareEngineering
24.02.2009  12
Domain Objects
 Find domain objects
 Tool  OOP (classes, encapsulation)
 Domain experts  business knowledge
 Purpose of an enterprise developer 
understand problem domain
 Start with key noun words
Clients, Cars, Models, Packages, etc.
BusinessSolutions
SoftwareEngineering
24.02.2009  13
Domain Objects sample
 Inter-dependency between upgrades
BusinessSolutions
SoftwareEngineering
24.02.2009  14
public class Car
{
private Model _model;
private List<Upgrade> _upgrades;
public void Add(Upgrade upgrade) { //todo }
}
public class Model
{
private int _id, _year;
private string _name;
public ReadOnlyCollection<Upgrade> GetAvailableUpgrades()
{
return null; //todo
}
}
public class Upgrade
{
private int _id;
private string _name;
public ReadOnlyCollection<Upgrade> RequiredUpgrades
{
get { return null; //todo }
}
}
BusinessSolutions
SoftwareEngineering
24.02.2009  15
public class Car
{
private Model _model; //todo where to initialize this?
private List<Upgrade> _upgrades;
public void Add(Upgrade upgrade)
{
_upgrades.Add(upgrade);
}
public ReadOnlyCollection<Upgrade> MissingUpgradeDependencies()
{
List<Upgrade> missingUpgrades = new List<Upgrade>();
foreach (Upgrade upgrade in _upgrades)
{
foreach (Upgrade dependentUpgrade in
upgrade.RequiredUpgrades)
{
if (!_upgrades.Contains(dependentUpgrade)
&& !missingUpgrades.Contains(dependentUpgrade))
{
missingUpgrades.Add(dependentUpgrade);
}
}
}
return missingUpgrades.AsReadOnly();
}
}
BusinessSolutions
SoftwareEngineering
24.02.2009  16
UI
 Domain is presentation layer independent
don‘t mix presentation and domain logic !
 Cohesive code  focus on one thing
– Redirect to another page
– Display error messages
– Request additional information
– NO DOMAIN FUNCTIONALITY !
 Code in codebehind will violate DRY
BusinessSolutions
SoftwareEngineering
24.02.2009  17
UI
 ASP.NET & WinForms with domain-centric code
– Databind to any .NET collection
 ASP.NET Page Framework Alternatives ?
– MVC Framework
– MonoRails, etc.
BusinessSolutions
SoftwareEngineering
24.02.2009  18
Tips & Tricks: Factory Pattern
public class Car
{
private Model _model;
private List<Upgrade> _upgrades;
private Car()
{
_upgrades = new List<Upgrade>();
}
public static Car CreateCar(Model model)
{
Car car = new Car();
car._model = model;
return car;
}
}
BusinessSolutions
SoftwareEngineering
24.02.2009  19
Factory Pattern: Advantages
 We can return a null object
 Chance to provide more meaningful function
names
User.CreateByCredentials(string username, string password)
User.CreateById(int id)
User.GetUsersByRole(string role)
BusinessSolutions
SoftwareEngineering
24.02.2009  20
Tips & Tricks: Access Modifiers
 Keep API small
 Prefer more restrective access modifier
 internal, visible within same assembly
BusinessSolutions
SoftwareEngineering
24.02.2009  21
Tips & Tricks: Interfaces
 To decouple the code
 Allows creating mock classes for testing
 Interface = contract
internal class SqlServerDataAccess {
internal List<Upgrade> RetrieveAllUpgrades() {
return null; //todo implement
}
}
public class Sample {
public void ASampleMethod() {
SqlServerDataAccess da = new SqlServerDataAccess();
List<Upgrade> upgrades = da.RetrieveAllUpgrades();
}
}
BusinessSolutions
SoftwareEngineering
24.02.2009  22
Tips & Tricks: Interfaces
internal interface IDataAccess
{
List<Upgrade> RetrieveAllUpgrades();
}
internal class DataAccess
{
internal static IDataAccess CreateInstance()
{
return new SqlServerDataAccess();
}
}
BusinessSolutions
SoftwareEngineering
24.02.2009  23
Tips & Tricks: Interfaces
internal class SqlServerDataAccess : IDataAccess
{
public List<Upgrade> RetrieveAllUpgrades()
{
return null; //todo implement
}
}
public class Sample
{
public void ASampleMethod()
{
private IDataAccess da = DataAccess.CreateInstance();
private List<Upgrade> upgrades = da.RetrieveAllUpgrades();
}
}
BusinessSolutions
SoftwareEngineering
24.02.2009  24
Tips & Tricks:
Information Hiding & Encapsulation
 Hide design decisions from other components
 Implentation changes without impact
 Example
– Private fields with public properties
BusinessSolutions
SoftwareEngineering
24.02.2009  25
PERSISTENCE
BusinessSolutions
SoftwareEngineering
24.02.2009  26
The Gap
 Relational database  objects
 Object-Relational Impedance Mismatch
 DataSets
– Relational representation within OO-code
• Poor testability
• Leaky abstraction
• Poor maintainability
• Poor performance
 or
 ... bridge the gap
BusinessSolutions
SoftwareEngineering
24.02.2009  27
public class Upgrade {
private int _id;
private string _name;
private string _description;
private decimal _price;
private List<Upgrade> _requiredUpgrades;
public int Id {
get { return _id; }
internal set { _id = value; }
}
public string Name {
get { return _name; }
set { _name = value; }
}
public string Description {
get { return _description; }
set { _description = value; }
}
public decimal Price {
get { return _price; }
set { _price = value; }
}
public List<Upgrade> RequiredUpgrades {
get { return _requiredUpgrades; }
}
}
BusinessSolutions
SoftwareEngineering
24.02.2009  28
CREATE TABLE Upgrades
(
Id INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
[Name] VARCHAR(64) NOT NULL,
Description VARCHAR(512) NOT NULL,
Price MONEY NOT NULL,
)
BusinessSolutions
SoftwareEngineering
24.02.2009  29
internal class SqlServerDataAccess
{
private static readonly string _connectionString = "FROM_CONFIG"
internal List<Upgrade> RetrieveAllUpgrades()
{
//use a sproc if you prefer
string sql = "SELECT Id, Name, Description, Price FROM
Upgrades";
using (SqlCommand command = new SqlCommand(sql))
{
using (SqlDataReader dataReader = ExecuteReader(command))
{
List<Upgrade> upgrades = new List<Upgrade>();
while (dataReader.Read())
{
upgrades.Add(DataMapper.CreateUpgrade(dataReader));
}
return upgrades;
}
}
}
...
}
BusinessSolutions
SoftwareEngineering
24.02.2009  30
internal static class DataMapper
{
internal static Upgrade CreateUpgrade(IDataReader dataReader)
{
Upgrade upgrade = new Upgrade();
upgrade.Id = Convert.ToInt32(dataReader["Id"]);
upgrade.Name = Convert.ToString(dataReader["Name"]);
upgrade.Description =
Convert.ToString(dataReader["Description"]);
upgrade.Price = Convert.ToDecimal(dataReader["Price"]);
return upgrade;
}
}
BusinessSolutions
SoftwareEngineering
24.02.2009  31
internal static class DataMapper
{
...
internal static SqlParameter[] ConvertUpgradeToParameters(Upgrade
upgrade)
{
SqlParameter[] parameters = new SqlParameter[4];
parameters[0] = new SqlParameter("Id", SqlDbType.Int);
parameters[0].Value = upgrade.Id;
parameters[1] = new SqlParameter("Name", SqlDbType.VarChar,
64);
parameters[1].Value = upgrade.Name;
parameters[2] = new SqlParameter("Description",
SqlDbType.VarChar, 512);
parameters[2].Value = upgrade.Description;
parameters[3] = new SqlParameter("Price", SqlDbType.Money);
parameters[3].Value = upgrade.Price;
return parameters;
}
}
BusinessSolutions
SoftwareEngineering
24.02.2009  32
We have a problem
 Relationships not handled
BusinessSolutions
SoftwareEngineering
24.02.2009  33
CREATE TABLE UpgradeDepencies
(
UpgradeId INT NOT NULL,
RequiredUpgradeId INT NOT NULL
)
BusinessSolutions
SoftwareEngineering
24.02.2009  34
internal List<Upgrade> RetrieveAllUpgrades() {
string sql = @"SELECT Id, Name, Description, Price FROM Upgrades;
SELECT UpgradeId, RequiredUpgradeId FROM
UpgradeDepencies";
using (SqlCommand command = new SqlCommand(sql)) {
using (SqlDataReader dataReader = ExecuteReader(command)) {
List<Upgrade> upgrades = new List<Upgrade>();
Dictionary<int, Upgrade> localCache = new Dictionary<int,
Upgrade>();
while (dataReader.Read()) {
Upgrade upgrade = DataMapper.CreateUpgrade(dataReader);
upgrades.Add(upgrade);
localCache.Add(upgrade.Id, upgrade);
}
dataReader.NextResult();
while (dataReader.Read()) {
int upgradeId = dataReader.GetInt32(0);
int requiredUpgradeId = dataReader.GetInt32(1);
Upgrade upgrade;
Upgrade required;
if (!localCache.TryGetValue(upgradeId, out upgrade) ||
!localCache.TryGetValue(requiredUpgradeId, out required))
{
//probably should throw an exception
//since our db is in a weird state
continue;
}
upgrade.RequiredUpgrades.Add(required);
}
return upgrades;
}
}
BusinessSolutions
SoftwareEngineering
24.02.2009  35
Limitations
 Much repetitive code
 No lazy loading
 No identity
 Persistence of updated, referenced objects
 Not flexible enough
BusinessSolutions
SoftwareEngineering
24.02.2009  36
DEPENDENCY INJECTION
BusinessSolutions
SoftwareEngineering
24.02.2009  37
„I would say that modern software engineering is the
ongoing refinement of the ever-increasing degrees of
decoupling. Yet, while the history of software shows that
coupling is bad, it also suggests that coupling is
unavoidable. An absolutely decoupled application is
useless because it adds no value. Developers can only
add value by coupling things together. The very act of
writing code is coupling one thing to another. The real
question is how to wisely choose what to be coupled to.”
JUVAL LÖWY
BusinessSolutions
SoftwareEngineering
24.02.2009  38
Decoupling
 Layering to provide extensibility
– Different databases
– Different frontends
– YAGNI ?
 Layering as result of cohesive and decoupled
code
 Decoupling = key ingredient in writing testable
code
1. Coupling/Decoupling
2. Unit Testing
BusinessSolutions
SoftwareEngineering
24.02.2009  39
Sneak Peak at Unit Testing
 Important: Unit-Testing
 Method to test might have a dependency
BusinessSolutions
SoftwareEngineering
24.02.2009  40
public class Car
{
private int _id;
public void Save()
{
if (!IsValid())
{
//todo: come up with a better exception
throw new InvalidOperationException("Car must be in valid
state");
}
if (_id == 0)
{
_id = DataAccess.CreateInstance().Save(this);
}
else
{
DataAccess.CreateInstance().Update(this);
}
}
private bool IsValid()
{
//todo: make sure the object is in a valid state
return true;
}
}
BusinessSolutions
SoftwareEngineering
24.02.2009  41
public class Car
{
private int _id;
public void Save()
{
if (!IsValid())
{
//todo: come up with a better exception
throw new InvalidOperationException("Car must be in valid
state");
}
if (_id == 0)
{
_id = DataAccess.CreateInstance().Save(this);
}
else
{
DataAccess.CreateInstance().Update(this);
}
}
private bool IsValid()
{
//todo: make sure the object is in a valid state
return true;
}
}
1. Make sure the correct exception is thrown when we try
to save a car which is in an invalid state,
2. Make sure the data access’ Save method is called
when it’s a new car, and
3. Make sure the Update method is called when it’s an
existing car.
Functionality of IsValid, Save and Update should
not be tested!
BusinessSolutions
SoftwareEngineering
24.02.2009  42
How to do that?
 Mocking frameworks will support that
 We can‘t use mocking frameworks with tightly
coupled code
BusinessSolutions
SoftwareEngineering
24.02.2009  43
Don‘t avoid coupling like the Plague
string site = "CodeBetter";
 Coupled to System.String
 Coupling isn‘t always bad
 But, no coupling to external components, code
that requires extensive setup or generates
random output
BusinessSolutions
SoftwareEngineering
24.02.2009  44
Dependency Injection
 A pattern that turns a hard-coded dependency
into something that can be injected at runtime
BusinessSolutions
SoftwareEngineering
24.02.2009  45
Constructor Injection
internal interface IDataAccess
{
int Save(Car car);
void Update(Car car);
}
internal class MockDataAccess : IDataAccess
{
private readonly List<Car> _cars = new List<Car>();
public int Save(Car car)
{
_cars.Add(car);
return _cars.Count;
}
public void Update(Car car)
{
_cars[_cars.IndexOf(car)] = car;
}
}
BusinessSolutions
SoftwareEngineering
24.02.2009  46
public class Car
{
private int _id;
private IDataAccess _dataProvider;
public Car() : this(new SqlServerDataAccess()) {}
internal Car(IDataAccess dataProvider) {
_dataProvider = dataProvider;
}
public void Save() {
if (!IsValid()) {
//todo: come up with a better exception
throw new InvalidOperationException("Car must be in valid
state");
}
if (_id == 0) {
_id = _dataProvider.Save(this);
}
else {
_dataProvider.Update(this);
}
}
}
BusinessSolutions
SoftwareEngineering
24.02.2009  47
Almost a test
public void AlmostATest()
{
Car car = new Car(new MockDataAccess());
car.Save();
if (car.Id != 1)
{
//something went wrong
}
}
BusinessSolutions
SoftwareEngineering
24.02.2009  48
DI Frameworks
 StructureMap
 Castle Windsor
 Unity (Microsoft)
 ObjectBuilder (Microsoft)
 Spring.NET
 Autofac
 Etc.
BusinessSolutions
SoftwareEngineering
24.02.2009  49
StructureMap configuration
<StructureMap>
<DefaultInstance
PluginType="CodeBetter.Foundations.IDataAccess,
CodeBetter.Foundations"
PluggedType="CodeBetter.Foundations.SqlDataAccess,
CodeBetter.Foundations"
/>
</StructureMap>
BusinessSolutions
SoftwareEngineering
24.02.2009  50
DI with StructureMap
Constructor Injection removed
public class Car
{
private int _id;
public void Save()
{
if (!IsValid())
{
//todo: come up with a better exception
throw new InvalidOperationException("The car must be in a valid
state");
}
IDataAccess dataAccess = ObjectFactory.GetInstance<IDataAccess>();
if (_id == 0)
{
_id = dataAccess.Save(this);
}
else
{
dataAccess.Update(this);
}
}
}
BusinessSolutions
SoftwareEngineering
24.02.2009  51
Inject a Mock
public void AlmostATest()
{
ObjectFactory.InjectStub(typeof(IDataAccess), new
MockDataAccess());
Car car = new Car();
car.Save();
if (car.Id != 1)
{
//something went wrong
}
ObjectFactory.ResetDefaults();
}
BusinessSolutions
SoftwareEngineering
24.02.2009  52
A Final Improvement
public static class DataFactory
{
public static IDataAccess CreateInstance
{
get
{
return ObjectFactory.GetInstance<IDataAccess>();
}
}
}
BusinessSolutions
SoftwareEngineering
24.02.2009  53
Reducing coupling
 Easy to do – great impact
 Required:
– A bit of knowledge
– Discipline
– Tools
 More benefits ?
– Unit Testing
BusinessSolutions
SoftwareEngineering
24.02.2009  54
UNIT TESTING
BusinessSolutions
SoftwareEngineering
24.02.2009  55
Unit Testing benefits
 Higher product quality
 Improved maintainability
 Confidence
– For changes, refactorings
BusinessSolutions
SoftwareEngineering
24.02.2009  56
Why unit testing
 Improved quality
but more than that
 Easier to change, maintain the system
 Better design
„TDD isn't about testing because you're not
thinking as a tester when doing TDD – you’re
thinking as a designer.”
SCOTT BELLWARE
BusinessSolutions
SoftwareEngineering
24.02.2009  57
The Tools
 nUnit / MSTest
Testing frameworks
 RhinoMocks / Moq / TypeMock
Mocking framework
 Visual Studio/ReSharper/TestDriven.NET
Integration/TestRunner
 Visual Studio/NCover
measures test coverage
BusinessSolutions
SoftwareEngineering
24.02.2009  58
nUnit - Startup
 Create Test project assembly
CodeBetter.Foundations.Tests
 Add references
nunit.framework.dll
Rhino.Mocks.dll
 Make internals visible (AssemblyInfo.cs)
[assembly:
InternalsVisibleTo(„CodeBetter.Foundations.Test
s“)]
BusinessSolutions
SoftwareEngineering
24.02.2009  59
Configuration with Attributes
using NUnit.Framework;
[TestFixture]
public class CarTests
{
[SetUp]
public void SetUp() { //todo }
[TearDown]
public void TearDown() { //todo }
[Test]
public void SaveThrowsExceptionWhenInvalid() { //todo }
[Test]
public void SaveCallsDataAccessAndSetsId() { //todo }
//more tests
}
BusinessSolutions
SoftwareEngineering
24.02.2009  60
Example
[Test]
public void MathUtilityReturnsZeroWhenNoParameters()
{
Assert.AreEqual(0, MathUtility.Add());
}
[Test]
public void MathUtilityReturnsValueWhenPassedOneValue()
{
Assert.AreEqual(10, MathUtility.Add(10));
}
[Test]
public void MathUtilityReturnsValueWhenPassedMultipleValues()
{
Assert.AreEqual(29, MathUtility.Add(10,2,17));
}
[Test]
public void MathUtilityWrapsOnOverflow()
{
Assert.AreEqual(-2, MathUtility.Add(int.MaxValue, int.MaxValue));
}
BusinessSolutions
SoftwareEngineering
24.02.2009  61
Assert
 Assert.IsFalse
 Assert.IsTrue
 Assert.IsNull
 Assert.IsNotNull
 Assert.AreSame
 Assert.AreNotEqual
 Assert.Greater
 Assert.IsInstanceOfType
 etc.
BusinessSolutions
SoftwareEngineering
24.02.2009  62
What is a Unit Test ?
 Test/validate behaviour at a very granular level
 One test for each behaviour
 Quick to run
BusinessSolutions
SoftwareEngineering
24.02.2009  63
Mocking
 Tested method often have dependencies
car.Save()  database
 Setup test database too complicated/slow
 We want to test only if Save() interacts properly
with DAL
 DAL will be tested separately
BusinessSolutions
SoftwareEngineering
24.02.2009  64
Mocking
 Manual Mocks
 Limitations
– Calls to our mock object not testable
 Solution
– Mock Framework: RhinoMocks
BusinessSolutions
SoftwareEngineering
24.02.2009  65
Mock – Test example
[TestFixture]
public class CarTest
{
[Test]
public void SaveCarCallsUpdateWhenAlreadyExistingCar()
{
MockRepository mocks = new MockRepository();
IDataAccess dataAccess = mocks.CreateMock<IDataAccess>();
ObjectFactory.InjectStub(typeof(IDataAccess), dataAccess);
Car car = new Car();
dataAccess.Update(car);
mocks.ReplayAll();
car.Id = 32;
car.Save();
mocks.VerifyAll();
ObjectFactory.ResetDefaults();
}
}
BusinessSolutions
SoftwareEngineering
24.02.2009  66
Let it fail
[Test]
public void SaveCarCallsUpdateWhenAlreadyExistingCar()
{
MockRepository mocks = new MockRepository();
IDataAccess dataAccess = mocks.CreateMock<IDataAccess>();
ObjectFactory.InjectStub(typeof(IDataAccess), dataAccess);
Car car = new Car();
dataAccess.Update(car);
dataAccess.Update(car);
mocks.ReplayAll();
car.Id = 32;
car.Save();
mocks.VerifyAll();
ObjectFactory.ResetDefaults();
}
BusinessSolutions
SoftwareEngineering
24.02.2009  67
Check return values
[Test]
public void SaveCarCallsSaveWhenNew()
{
MockRepository mocks = new MockRepository();
IDataAccess dataAccess = mocks.CreateMock< IDataAccess>();
ObjectFactory.InjectStub(typeof(IDataAccess), dataAccess);
private Car car = new Car();
Expect.Call(dataAccess.Save(car)).Return(389);
mocks.ReplayAll();
car.Save();
mocks.VerifyAll();
Assert.AreEqual(389, car.Id);
ObjectFactory.ResetDefaults();
}
BusinessSolutions
SoftwareEngineering
24.02.2009  68
Extract repetitive code
[TestFixture]
public class CarTest
{
private MockRepository _mocks;
private IDataAccess _dataAccess;
[SetUp]
public void SetUp()
{
_mocks = new MockRepository();
_dataAccess = _mocks.CreateMock<IDataAccess>();
ObjectFactory.InjectStub(typeof(IDataAccess), _dataAccess);
}
[TearDown]
public void TearDown()
{
_mocks.VerifyAll();
}
...
}
BusinessSolutions
SoftwareEngineering
24.02.2009  69
Test for exceptions
[TestFixture]
public class CarTest
{
...
[Test,
ExpectedException("CodeBetter.Foundations.PersistenceException")]
public void SaveCarCallsSaveWhenNew()
{
Car car = new Car();
Expect.Call(_dataAccess.Save(car)).Return(0);
_mocks.ReplayAll();
car.Save();
}
}
BusinessSolutions
SoftwareEngineering
24.02.2009  70
TDD
1. Write test
2. Let test fail
3. Write code to make the test pass
red  green  refactor
BusinessSolutions
SoftwareEngineering
24.02.2009  71
UI and Database Testing
 ASP.NET Testing
– Very tight coupled
– Not easy/worth the effort to test
 Data Access Layer Testing
– Possible & recommended
– Test-Database
– Use SetUp and TearDown to create a known state
BusinessSolutions
SoftwareEngineering
24.02.2009  72
OBJECT RELATIONAL MAPPERS
BusinessSolutions
SoftwareEngineering
24.02.2009  73
„With very few exceptions, I'd say that at this point that
if you're writing ADO.Net code or SQL by hand, you're
stealing money from your employer or client.”
JEREMY D. MILLER
BusinessSolutions
SoftwareEngineering
24.02.2009  74
ORM Benefits
 A lot less code => more maintainable system
 Abstraction from data source (mapping)
 Code becomes simpler, low impedance
mismatch
BusinessSolutions
SoftwareEngineering
24.02.2009  75
NHibernate
 Open-Source ORM framework
 Complex 
 Completely transparent 
– No base class, no decorator attributes
– Unit testing of domain layer possible
 Maps domain objects to database objects
– Decouples code from specific DB implementation
BusinessSolutions
SoftwareEngineering
24.02.2009  76
NHibernate configuration
<configuration>
<configSections>
<section name="hibernate-configuration"
type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" />
</configSections>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="hibernate.dialect">
NHibernate.Dialect.MsSql2005Dialect </property>
<property name="hibernate.connection.provider">
NHibernate.Connection.DriverConnectionProvider </property>
<property name="hibernate.connection.connection_string">
Server=SERVER;Initial Catalog=DB;User Id=USER;Password=PASSWORD;
</property>
<mapping assembly="CodeBetter.Foundations" />
</session-factory>
</hibernate-configuration>
</configuration>
BusinessSolutions
SoftwareEngineering
24.02.2009  77
NHibernate Mapping File
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="CodeBetter.Foundations"
namespace="CodeBetter.Foundations">
<class name="Model" table="Models" lazy="true" proxy="Model">
<id name="Id" column="Id" type="int" access="field.lowercase-
underscore">
<generator class="native" />
</id>
<property name="Name" column="Name"
type="string" not-null="true" length="64" />
<property name="Description" column="Description"
type="string" not-null="true" />
<property name="Price" column="Price"
type="double" not-null="true" />
</class>
</hibernate-mapping>
BusinessSolutions
SoftwareEngineering
24.02.2009  78
Interacting with the database
private static ISessionFactory _sessionFactory;
public void Sample()
{
//Let's add a new car model
Model model = new Model();
model.Name = "Hummbee";
model.Description = "Great handling, built-in GPS to always find
your
way back home, Hummbee2Hummbe(tm)
communication";
model.Price = 50000.00;
ISession session = _sessionFactory.OpenSession();
session.Save(model);
//Let's discount the x149 model
IQuery query = session.CreateQuery("from Model model where
model.Name = ?");
Model model = query.SetString(0, "X149").UniqueResult<Model>();
model.Price -= 5000;
ISession session = _sessionFactory.OpenSession();
session.Update(model);
}
BusinessSolutions
SoftwareEngineering
24.02.2009  79
Relationships
public SalesPerson SalesPerson { get; set; }
<many-to-one name="SalesPerson"
class="SalesPerson"
column="SalesPersonId"
not-null="true"/>
BusinessSolutions
SoftwareEngineering
24.02.2009  80
The other side of the relationship
private IList<Sale> _sales;
public IList<Sale> Sales
{
get { return _sales; }
}
<bag name="Sales" access="field.lowercase-underscore"
table="Sales" inverse="true" cascade="all">
<key column="SalesPersonId" />
<one-to-many class="Sale" />
</bag>
BusinessSolutions
SoftwareEngineering
24.02.2009  81
Querying
string lastName = "allen";
ISession session = _sessionFactory.OpenSession();
//retrieve a salesperson by last name
IQuery query = s.CreateQuery("from SalesPerson p where p.LastName =
'allen'");
SalesPerson p = query.UniqueResult<SalesPerson>();
//same as above but in 1 line, and with the last name as a variable
SalesPerson p = session.CreateQuery("from SalesPerson p where
p.LastName = ?").SetString(0, lastName).UniqueResult<SalesPerson>();
//people with few sales
IList<SalesPerson> slackers = session.CreateQuery("from SalesPerson
person where size(person.Sales) < 5").List<SalesPerson>();
BusinessSolutions
SoftwareEngineering
24.02.2009  82
Lazy Loading
 By default, collections are lazy loaded
e.g. SalesPerson.Sales
 lazy="false"
 Session.Load<T>(id) loads Proxy
BusinessSolutions
SoftwareEngineering
24.02.2009  83
Lazy Loading
Sale sale = new Sale(session.Load<Model>(1), DateTime.Now, 46000.00);
salesPerson.AddSales(sale);
session.SaveOrUpdate(salesPerson);
BusinessSolutions
SoftwareEngineering
24.02.2009  84
WRAPPING IT UP
BusinessSolutions
SoftwareEngineering
24.02.2009  85
Wrapping it up
 The most flexible solution is the simplest.
– YAGNI, DRY, KISS and explicitness.
 Coupling is unavoidable, but must be
minimized.
– The more dependencies you have, the harder your
code is to change.
– Unit Tests are the path to mastering low-coupling.
Badly coupled code will be impossible to test.
BusinessSolutions
SoftwareEngineering
24.02.2009  86
Wrapping it up
 Higher quality should be good enough reason
to write tests, but, there are better reasons.
– Testing helps you identify bad coupling.
– Testing helps you find awkwardness in your API.
– Testing helps you document behavior and
expectations.
– Testing lets you make small and radical changes
with far greater confidence and far less risk.
BusinessSolutions
SoftwareEngineering
24.02.2009  87
Wrapping it up
 It's possible to build successful software
without being Agile - but it's far less likely and a
lot less fun.
– ongoing customer collaboration
– iterative development
– No signed off specifications before starting to
develop
BusinessSolutions
SoftwareEngineering
24.02.2009  88
References
 Foundations of Programming, Karl Seguin
http://codebetter.com/blogs/karlseguin/archive/2008
/06/24/foundations-of-programming-ebook.aspx
with additional topics
– Back to Basics: Memory
– Back to Basics: Exceptions
– Back to Basics: Proxy This and
Proxy That
BusinessSolutions
SoftwareEngineering
24.02.2009  89
Links
 http://www.codebetter.com
 http://structuremap.sourceforge.net
 http://www.nunit.org
 http://ayende.com/projects/rhino-mocks.aspx
 http://www.nhibernate.org
BusinessSolutions
SoftwareEngineering
24.02.2009  90
THE END
Questions / Discussion

More Related Content

Similar to Foundations of programming

SPCA2013 - Building a SharePoint Factory
SPCA2013 - Building a SharePoint FactorySPCA2013 - Building a SharePoint Factory
SPCA2013 - Building a SharePoint Factory
NCCOMMS
 
Optimizing Code Reusability for SharePoint using Linq to SharePoint & the MVP...
Optimizing Code Reusability for SharePoint using Linq to SharePoint & the MVP...Optimizing Code Reusability for SharePoint using Linq to SharePoint & the MVP...
Optimizing Code Reusability for SharePoint using Linq to SharePoint & the MVP...
Sparkhound Inc.
 
Neoito — Design patterns and depenedency injection
Neoito — Design patterns and depenedency injectionNeoito — Design patterns and depenedency injection
Neoito — Design patterns and depenedency injection
Neoito
 
Introduction to OO, Java and Eclipse/WebSphere
Introduction to OO, Java and Eclipse/WebSphereIntroduction to OO, Java and Eclipse/WebSphere
Introduction to OO, Java and Eclipse/WebSphere
eLink Business Innovations
 
Clean Architecture @ Taxibeat
Clean Architecture @ TaxibeatClean Architecture @ Taxibeat
Clean Architecture @ Taxibeat
Michael Bakogiannis
 
Folio3 - An Introduction to PHP Yii
Folio3 - An Introduction to PHP YiiFolio3 - An Introduction to PHP Yii
Folio3 - An Introduction to PHP Yii
Folio3 Software
 
Indore MuleSoft Meetup #5 April 2022 MDynamics 65.pptx
Indore MuleSoft Meetup #5 April 2022 MDynamics 65.pptxIndore MuleSoft Meetup #5 April 2022 MDynamics 65.pptx
Indore MuleSoft Meetup #5 April 2022 MDynamics 65.pptx
IndoreMulesoftMeetup
 
Developing Next-Gen Enterprise Web Application
Developing Next-Gen Enterprise Web ApplicationDeveloping Next-Gen Enterprise Web Application
Developing Next-Gen Enterprise Web Application
Mark Gu
 
Introduction to Force.com
Introduction to Force.comIntroduction to Force.com
Introduction to Force.com
IMC Institute
 
Connect 2014 - BP202: Rapid XPages Development Using the Application Layout C...
Connect 2014 - BP202: Rapid XPages Development Using the Application Layout C...Connect 2014 - BP202: Rapid XPages Development Using the Application Layout C...
Connect 2014 - BP202: Rapid XPages Development Using the Application Layout C...
Howard Greenberg
 
Atl elevate programmatic developer slides
Atl elevate programmatic developer slidesAtl elevate programmatic developer slides
Atl elevate programmatic developer slides
David Scruggs
 
.NET Portfolio
.NET Portfolio.NET Portfolio
.NET Portfoliomwillmer
 
Actively looking for an opportunity to work as a challenging Dot Net Developer
Actively looking for an opportunity to work as a challenging Dot Net DeveloperActively looking for an opportunity to work as a challenging Dot Net Developer
Actively looking for an opportunity to work as a challenging Dot Net Developer
Karthik Reddy
 
Actively looking for an opportunity to work as a challenging Dot Net Developer
Actively looking for an opportunity to work as a challenging Dot Net DeveloperActively looking for an opportunity to work as a challenging Dot Net Developer
Actively looking for an opportunity to work as a challenging Dot Net Developer
Karthik Reddy
 
Apex Enterprise Patterns: Building Strong Foundations
Apex Enterprise Patterns: Building Strong FoundationsApex Enterprise Patterns: Building Strong Foundations
Apex Enterprise Patterns: Building Strong Foundations
Salesforce Developers
 
The Magic Of Application Lifecycle Management In Vs Public
The Magic Of Application Lifecycle Management In Vs PublicThe Magic Of Application Lifecycle Management In Vs Public
The Magic Of Application Lifecycle Management In Vs Public
David Solivan
 
2008 - TechDays PT: Building Software + Services with Volta
2008 - TechDays PT: Building Software + Services with Volta2008 - TechDays PT: Building Software + Services with Volta
2008 - TechDays PT: Building Software + Services with Volta
Daniel Fisher
 
Javascript Design Patterns
Javascript Design PatternsJavascript Design Patterns
Javascript Design Patterns
Iván Fernández Perea
 

Similar to Foundations of programming (20)

Pratk kambe rac
Pratk kambe racPratk kambe rac
Pratk kambe rac
 
SPCA2013 - Building a SharePoint Factory
SPCA2013 - Building a SharePoint FactorySPCA2013 - Building a SharePoint Factory
SPCA2013 - Building a SharePoint Factory
 
Optimizing Code Reusability for SharePoint using Linq to SharePoint & the MVP...
Optimizing Code Reusability for SharePoint using Linq to SharePoint & the MVP...Optimizing Code Reusability for SharePoint using Linq to SharePoint & the MVP...
Optimizing Code Reusability for SharePoint using Linq to SharePoint & the MVP...
 
Neoito — Design patterns and depenedency injection
Neoito — Design patterns and depenedency injectionNeoito — Design patterns and depenedency injection
Neoito — Design patterns and depenedency injection
 
Introduction to OO, Java and Eclipse/WebSphere
Introduction to OO, Java and Eclipse/WebSphereIntroduction to OO, Java and Eclipse/WebSphere
Introduction to OO, Java and Eclipse/WebSphere
 
Clean Architecture @ Taxibeat
Clean Architecture @ TaxibeatClean Architecture @ Taxibeat
Clean Architecture @ Taxibeat
 
Folio3 - An Introduction to PHP Yii
Folio3 - An Introduction to PHP YiiFolio3 - An Introduction to PHP Yii
Folio3 - An Introduction to PHP Yii
 
Indore MuleSoft Meetup #5 April 2022 MDynamics 65.pptx
Indore MuleSoft Meetup #5 April 2022 MDynamics 65.pptxIndore MuleSoft Meetup #5 April 2022 MDynamics 65.pptx
Indore MuleSoft Meetup #5 April 2022 MDynamics 65.pptx
 
Developing Next-Gen Enterprise Web Application
Developing Next-Gen Enterprise Web ApplicationDeveloping Next-Gen Enterprise Web Application
Developing Next-Gen Enterprise Web Application
 
Introduction to Force.com
Introduction to Force.comIntroduction to Force.com
Introduction to Force.com
 
ASP.NET MVC3 RAD
ASP.NET MVC3 RADASP.NET MVC3 RAD
ASP.NET MVC3 RAD
 
Connect 2014 - BP202: Rapid XPages Development Using the Application Layout C...
Connect 2014 - BP202: Rapid XPages Development Using the Application Layout C...Connect 2014 - BP202: Rapid XPages Development Using the Application Layout C...
Connect 2014 - BP202: Rapid XPages Development Using the Application Layout C...
 
Atl elevate programmatic developer slides
Atl elevate programmatic developer slidesAtl elevate programmatic developer slides
Atl elevate programmatic developer slides
 
.NET Portfolio
.NET Portfolio.NET Portfolio
.NET Portfolio
 
Actively looking for an opportunity to work as a challenging Dot Net Developer
Actively looking for an opportunity to work as a challenging Dot Net DeveloperActively looking for an opportunity to work as a challenging Dot Net Developer
Actively looking for an opportunity to work as a challenging Dot Net Developer
 
Actively looking for an opportunity to work as a challenging Dot Net Developer
Actively looking for an opportunity to work as a challenging Dot Net DeveloperActively looking for an opportunity to work as a challenging Dot Net Developer
Actively looking for an opportunity to work as a challenging Dot Net Developer
 
Apex Enterprise Patterns: Building Strong Foundations
Apex Enterprise Patterns: Building Strong FoundationsApex Enterprise Patterns: Building Strong Foundations
Apex Enterprise Patterns: Building Strong Foundations
 
The Magic Of Application Lifecycle Management In Vs Public
The Magic Of Application Lifecycle Management In Vs PublicThe Magic Of Application Lifecycle Management In Vs Public
The Magic Of Application Lifecycle Management In Vs Public
 
2008 - TechDays PT: Building Software + Services with Volta
2008 - TechDays PT: Building Software + Services with Volta2008 - TechDays PT: Building Software + Services with Volta
2008 - TechDays PT: Building Software + Services with Volta
 
Javascript Design Patterns
Javascript Design PatternsJavascript Design Patterns
Javascript Design Patterns
 

Recently uploaded

Graspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code AnalysisGraspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code Analysis
Aftab Hussain
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
Łukasz Chruściel
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
Max Andersen
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
rickgrimesss22
 
Hand Rolled Applicative User Validation Code Kata
Hand Rolled Applicative User ValidationCode KataHand Rolled Applicative User ValidationCode Kata
Hand Rolled Applicative User Validation Code Kata
Philip Schwarz
 
SWEBOK and Education at FUSE Okinawa 2024
SWEBOK and Education at FUSE Okinawa 2024SWEBOK and Education at FUSE Okinawa 2024
SWEBOK and Education at FUSE Okinawa 2024
Hironori Washizaki
 
Artificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension FunctionsArtificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension Functions
Octavian Nadolu
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
NYGGS Automation Suite
 
GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
Neo4j
 
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of CodeA Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
Aftab Hussain
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
Philip Schwarz
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Mind IT Systems
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
Safe Software
 
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdfVitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke
 
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
kalichargn70th171
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
Boni García
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Crescat
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
Ayan Halder
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
Paco van Beckhoven
 

Recently uploaded (20)

Graspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code AnalysisGraspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code Analysis
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
 
Hand Rolled Applicative User Validation Code Kata
Hand Rolled Applicative User ValidationCode KataHand Rolled Applicative User ValidationCode Kata
Hand Rolled Applicative User Validation Code Kata
 
SWEBOK and Education at FUSE Okinawa 2024
SWEBOK and Education at FUSE Okinawa 2024SWEBOK and Education at FUSE Okinawa 2024
SWEBOK and Education at FUSE Okinawa 2024
 
Artificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension FunctionsArtificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension Functions
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
 
GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
 
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of CodeA Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
 
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdfVitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdf
 
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
 

Foundations of programming

  • 2. BusinessSolutions SoftwareEngineering 24.02.2009  2 Foundations of Programming Based on a free EBook from Karl Seguin www.codebetter.com
  • 3. BusinessSolutions SoftwareEngineering 24.02.2009  3 Agenda  ALT.NET  Domain Driven Design  Persistence  Dependency Injection  Unit Testing  Object Relational Mappers  Conclusion
  • 4. BusinessSolutions SoftwareEngineering 24.02.2009  4 ALT.NET  The MSDN Way vs. ALT.NET  Data centric versus Domain driven  Goals: Maintainability – > 50% in maintenance state – iterative development  continuous changes
  • 5. BusinessSolutions SoftwareEngineering 24.02.2009  5 ALT.NET – Principles  Simplicity  YAGNI  Last Responsible Moment  DRY  Explicitness and Cohesion  Coupling  Unit Tests and Continuous Integration
  • 7. BusinessSolutions SoftwareEngineering 24.02.2009  7 „What is Design? It’s where you stand with a foot in two worlds – the world of technology and the world of people and human purposes – and you try to bring the two together.” MITCHELL KAPOR
  • 8. BusinessSolutions SoftwareEngineering 24.02.2009  8 Data Driven Design  How to design your system? – Data-driven or domain-centric  Build your system around the data  Database first  Then mimick in .NET  Great MS tool support
  • 9. BusinessSolutions SoftwareEngineering 24.02.2009  9 Domain Driven Design (DDD)  Focuses on the problem domain  Data AND behaviour  Tool  OOP
  • 10. BusinessSolutions SoftwareEngineering 24.02.2009  10 „In the past, I'd frequently get pissed off with clients. They were annoying, didn't know what they wanted and always made the wrong choice. Once I actually thought about it though, I realized that I wasn't nearly as smart as I thought I was. The client knew far more about his or her business than I did. Not only that, but it was their money and my job was to make them get the most out of it. As the relationship turned more collaborative and positive, not only did the end result greatly improve, but programming became fun again.” KARL SEGUIN
  • 11. BusinessSolutions SoftwareEngineering 24.02.2009  11 Users, Clients and Stakeholders  Client: pays the bill, should make decisions about features and priorities, often User  User: uses System, different types  Stakeholders: anyone with a stake in the system  Domain experts
  • 12. BusinessSolutions SoftwareEngineering 24.02.2009  12 Domain Objects  Find domain objects  Tool  OOP (classes, encapsulation)  Domain experts  business knowledge  Purpose of an enterprise developer  understand problem domain  Start with key noun words Clients, Cars, Models, Packages, etc.
  • 13. BusinessSolutions SoftwareEngineering 24.02.2009  13 Domain Objects sample  Inter-dependency between upgrades
  • 14. BusinessSolutions SoftwareEngineering 24.02.2009  14 public class Car { private Model _model; private List<Upgrade> _upgrades; public void Add(Upgrade upgrade) { //todo } } public class Model { private int _id, _year; private string _name; public ReadOnlyCollection<Upgrade> GetAvailableUpgrades() { return null; //todo } } public class Upgrade { private int _id; private string _name; public ReadOnlyCollection<Upgrade> RequiredUpgrades { get { return null; //todo } } }
  • 15. BusinessSolutions SoftwareEngineering 24.02.2009  15 public class Car { private Model _model; //todo where to initialize this? private List<Upgrade> _upgrades; public void Add(Upgrade upgrade) { _upgrades.Add(upgrade); } public ReadOnlyCollection<Upgrade> MissingUpgradeDependencies() { List<Upgrade> missingUpgrades = new List<Upgrade>(); foreach (Upgrade upgrade in _upgrades) { foreach (Upgrade dependentUpgrade in upgrade.RequiredUpgrades) { if (!_upgrades.Contains(dependentUpgrade) && !missingUpgrades.Contains(dependentUpgrade)) { missingUpgrades.Add(dependentUpgrade); } } } return missingUpgrades.AsReadOnly(); } }
  • 16. BusinessSolutions SoftwareEngineering 24.02.2009  16 UI  Domain is presentation layer independent don‘t mix presentation and domain logic !  Cohesive code  focus on one thing – Redirect to another page – Display error messages – Request additional information – NO DOMAIN FUNCTIONALITY !  Code in codebehind will violate DRY
  • 17. BusinessSolutions SoftwareEngineering 24.02.2009  17 UI  ASP.NET & WinForms with domain-centric code – Databind to any .NET collection  ASP.NET Page Framework Alternatives ? – MVC Framework – MonoRails, etc.
  • 18. BusinessSolutions SoftwareEngineering 24.02.2009  18 Tips & Tricks: Factory Pattern public class Car { private Model _model; private List<Upgrade> _upgrades; private Car() { _upgrades = new List<Upgrade>(); } public static Car CreateCar(Model model) { Car car = new Car(); car._model = model; return car; } }
  • 19. BusinessSolutions SoftwareEngineering 24.02.2009  19 Factory Pattern: Advantages  We can return a null object  Chance to provide more meaningful function names User.CreateByCredentials(string username, string password) User.CreateById(int id) User.GetUsersByRole(string role)
  • 20. BusinessSolutions SoftwareEngineering 24.02.2009  20 Tips & Tricks: Access Modifiers  Keep API small  Prefer more restrective access modifier  internal, visible within same assembly
  • 21. BusinessSolutions SoftwareEngineering 24.02.2009  21 Tips & Tricks: Interfaces  To decouple the code  Allows creating mock classes for testing  Interface = contract internal class SqlServerDataAccess { internal List<Upgrade> RetrieveAllUpgrades() { return null; //todo implement } } public class Sample { public void ASampleMethod() { SqlServerDataAccess da = new SqlServerDataAccess(); List<Upgrade> upgrades = da.RetrieveAllUpgrades(); } }
  • 22. BusinessSolutions SoftwareEngineering 24.02.2009  22 Tips & Tricks: Interfaces internal interface IDataAccess { List<Upgrade> RetrieveAllUpgrades(); } internal class DataAccess { internal static IDataAccess CreateInstance() { return new SqlServerDataAccess(); } }
  • 23. BusinessSolutions SoftwareEngineering 24.02.2009  23 Tips & Tricks: Interfaces internal class SqlServerDataAccess : IDataAccess { public List<Upgrade> RetrieveAllUpgrades() { return null; //todo implement } } public class Sample { public void ASampleMethod() { private IDataAccess da = DataAccess.CreateInstance(); private List<Upgrade> upgrades = da.RetrieveAllUpgrades(); } }
  • 24. BusinessSolutions SoftwareEngineering 24.02.2009  24 Tips & Tricks: Information Hiding & Encapsulation  Hide design decisions from other components  Implentation changes without impact  Example – Private fields with public properties
  • 26. BusinessSolutions SoftwareEngineering 24.02.2009  26 The Gap  Relational database  objects  Object-Relational Impedance Mismatch  DataSets – Relational representation within OO-code • Poor testability • Leaky abstraction • Poor maintainability • Poor performance  or  ... bridge the gap
  • 27. BusinessSolutions SoftwareEngineering 24.02.2009  27 public class Upgrade { private int _id; private string _name; private string _description; private decimal _price; private List<Upgrade> _requiredUpgrades; public int Id { get { return _id; } internal set { _id = value; } } public string Name { get { return _name; } set { _name = value; } } public string Description { get { return _description; } set { _description = value; } } public decimal Price { get { return _price; } set { _price = value; } } public List<Upgrade> RequiredUpgrades { get { return _requiredUpgrades; } } }
  • 28. BusinessSolutions SoftwareEngineering 24.02.2009  28 CREATE TABLE Upgrades ( Id INT IDENTITY(1,1) NOT NULL PRIMARY KEY, [Name] VARCHAR(64) NOT NULL, Description VARCHAR(512) NOT NULL, Price MONEY NOT NULL, )
  • 29. BusinessSolutions SoftwareEngineering 24.02.2009  29 internal class SqlServerDataAccess { private static readonly string _connectionString = "FROM_CONFIG" internal List<Upgrade> RetrieveAllUpgrades() { //use a sproc if you prefer string sql = "SELECT Id, Name, Description, Price FROM Upgrades"; using (SqlCommand command = new SqlCommand(sql)) { using (SqlDataReader dataReader = ExecuteReader(command)) { List<Upgrade> upgrades = new List<Upgrade>(); while (dataReader.Read()) { upgrades.Add(DataMapper.CreateUpgrade(dataReader)); } return upgrades; } } } ... }
  • 30. BusinessSolutions SoftwareEngineering 24.02.2009  30 internal static class DataMapper { internal static Upgrade CreateUpgrade(IDataReader dataReader) { Upgrade upgrade = new Upgrade(); upgrade.Id = Convert.ToInt32(dataReader["Id"]); upgrade.Name = Convert.ToString(dataReader["Name"]); upgrade.Description = Convert.ToString(dataReader["Description"]); upgrade.Price = Convert.ToDecimal(dataReader["Price"]); return upgrade; } }
  • 31. BusinessSolutions SoftwareEngineering 24.02.2009  31 internal static class DataMapper { ... internal static SqlParameter[] ConvertUpgradeToParameters(Upgrade upgrade) { SqlParameter[] parameters = new SqlParameter[4]; parameters[0] = new SqlParameter("Id", SqlDbType.Int); parameters[0].Value = upgrade.Id; parameters[1] = new SqlParameter("Name", SqlDbType.VarChar, 64); parameters[1].Value = upgrade.Name; parameters[2] = new SqlParameter("Description", SqlDbType.VarChar, 512); parameters[2].Value = upgrade.Description; parameters[3] = new SqlParameter("Price", SqlDbType.Money); parameters[3].Value = upgrade.Price; return parameters; } }
  • 32. BusinessSolutions SoftwareEngineering 24.02.2009  32 We have a problem  Relationships not handled
  • 33. BusinessSolutions SoftwareEngineering 24.02.2009  33 CREATE TABLE UpgradeDepencies ( UpgradeId INT NOT NULL, RequiredUpgradeId INT NOT NULL )
  • 34. BusinessSolutions SoftwareEngineering 24.02.2009  34 internal List<Upgrade> RetrieveAllUpgrades() { string sql = @"SELECT Id, Name, Description, Price FROM Upgrades; SELECT UpgradeId, RequiredUpgradeId FROM UpgradeDepencies"; using (SqlCommand command = new SqlCommand(sql)) { using (SqlDataReader dataReader = ExecuteReader(command)) { List<Upgrade> upgrades = new List<Upgrade>(); Dictionary<int, Upgrade> localCache = new Dictionary<int, Upgrade>(); while (dataReader.Read()) { Upgrade upgrade = DataMapper.CreateUpgrade(dataReader); upgrades.Add(upgrade); localCache.Add(upgrade.Id, upgrade); } dataReader.NextResult(); while (dataReader.Read()) { int upgradeId = dataReader.GetInt32(0); int requiredUpgradeId = dataReader.GetInt32(1); Upgrade upgrade; Upgrade required; if (!localCache.TryGetValue(upgradeId, out upgrade) || !localCache.TryGetValue(requiredUpgradeId, out required)) { //probably should throw an exception //since our db is in a weird state continue; } upgrade.RequiredUpgrades.Add(required); } return upgrades; } }
  • 35. BusinessSolutions SoftwareEngineering 24.02.2009  35 Limitations  Much repetitive code  No lazy loading  No identity  Persistence of updated, referenced objects  Not flexible enough
  • 37. BusinessSolutions SoftwareEngineering 24.02.2009  37 „I would say that modern software engineering is the ongoing refinement of the ever-increasing degrees of decoupling. Yet, while the history of software shows that coupling is bad, it also suggests that coupling is unavoidable. An absolutely decoupled application is useless because it adds no value. Developers can only add value by coupling things together. The very act of writing code is coupling one thing to another. The real question is how to wisely choose what to be coupled to.” JUVAL LÖWY
  • 38. BusinessSolutions SoftwareEngineering 24.02.2009  38 Decoupling  Layering to provide extensibility – Different databases – Different frontends – YAGNI ?  Layering as result of cohesive and decoupled code  Decoupling = key ingredient in writing testable code 1. Coupling/Decoupling 2. Unit Testing
  • 39. BusinessSolutions SoftwareEngineering 24.02.2009  39 Sneak Peak at Unit Testing  Important: Unit-Testing  Method to test might have a dependency
  • 40. BusinessSolutions SoftwareEngineering 24.02.2009  40 public class Car { private int _id; public void Save() { if (!IsValid()) { //todo: come up with a better exception throw new InvalidOperationException("Car must be in valid state"); } if (_id == 0) { _id = DataAccess.CreateInstance().Save(this); } else { DataAccess.CreateInstance().Update(this); } } private bool IsValid() { //todo: make sure the object is in a valid state return true; } }
  • 41. BusinessSolutions SoftwareEngineering 24.02.2009  41 public class Car { private int _id; public void Save() { if (!IsValid()) { //todo: come up with a better exception throw new InvalidOperationException("Car must be in valid state"); } if (_id == 0) { _id = DataAccess.CreateInstance().Save(this); } else { DataAccess.CreateInstance().Update(this); } } private bool IsValid() { //todo: make sure the object is in a valid state return true; } } 1. Make sure the correct exception is thrown when we try to save a car which is in an invalid state, 2. Make sure the data access’ Save method is called when it’s a new car, and 3. Make sure the Update method is called when it’s an existing car. Functionality of IsValid, Save and Update should not be tested!
  • 42. BusinessSolutions SoftwareEngineering 24.02.2009  42 How to do that?  Mocking frameworks will support that  We can‘t use mocking frameworks with tightly coupled code
  • 43. BusinessSolutions SoftwareEngineering 24.02.2009  43 Don‘t avoid coupling like the Plague string site = "CodeBetter";  Coupled to System.String  Coupling isn‘t always bad  But, no coupling to external components, code that requires extensive setup or generates random output
  • 44. BusinessSolutions SoftwareEngineering 24.02.2009  44 Dependency Injection  A pattern that turns a hard-coded dependency into something that can be injected at runtime
  • 45. BusinessSolutions SoftwareEngineering 24.02.2009  45 Constructor Injection internal interface IDataAccess { int Save(Car car); void Update(Car car); } internal class MockDataAccess : IDataAccess { private readonly List<Car> _cars = new List<Car>(); public int Save(Car car) { _cars.Add(car); return _cars.Count; } public void Update(Car car) { _cars[_cars.IndexOf(car)] = car; } }
  • 46. BusinessSolutions SoftwareEngineering 24.02.2009  46 public class Car { private int _id; private IDataAccess _dataProvider; public Car() : this(new SqlServerDataAccess()) {} internal Car(IDataAccess dataProvider) { _dataProvider = dataProvider; } public void Save() { if (!IsValid()) { //todo: come up with a better exception throw new InvalidOperationException("Car must be in valid state"); } if (_id == 0) { _id = _dataProvider.Save(this); } else { _dataProvider.Update(this); } } }
  • 47. BusinessSolutions SoftwareEngineering 24.02.2009  47 Almost a test public void AlmostATest() { Car car = new Car(new MockDataAccess()); car.Save(); if (car.Id != 1) { //something went wrong } }
  • 48. BusinessSolutions SoftwareEngineering 24.02.2009  48 DI Frameworks  StructureMap  Castle Windsor  Unity (Microsoft)  ObjectBuilder (Microsoft)  Spring.NET  Autofac  Etc.
  • 49. BusinessSolutions SoftwareEngineering 24.02.2009  49 StructureMap configuration <StructureMap> <DefaultInstance PluginType="CodeBetter.Foundations.IDataAccess, CodeBetter.Foundations" PluggedType="CodeBetter.Foundations.SqlDataAccess, CodeBetter.Foundations" /> </StructureMap>
  • 50. BusinessSolutions SoftwareEngineering 24.02.2009  50 DI with StructureMap Constructor Injection removed public class Car { private int _id; public void Save() { if (!IsValid()) { //todo: come up with a better exception throw new InvalidOperationException("The car must be in a valid state"); } IDataAccess dataAccess = ObjectFactory.GetInstance<IDataAccess>(); if (_id == 0) { _id = dataAccess.Save(this); } else { dataAccess.Update(this); } } }
  • 51. BusinessSolutions SoftwareEngineering 24.02.2009  51 Inject a Mock public void AlmostATest() { ObjectFactory.InjectStub(typeof(IDataAccess), new MockDataAccess()); Car car = new Car(); car.Save(); if (car.Id != 1) { //something went wrong } ObjectFactory.ResetDefaults(); }
  • 52. BusinessSolutions SoftwareEngineering 24.02.2009  52 A Final Improvement public static class DataFactory { public static IDataAccess CreateInstance { get { return ObjectFactory.GetInstance<IDataAccess>(); } } }
  • 53. BusinessSolutions SoftwareEngineering 24.02.2009  53 Reducing coupling  Easy to do – great impact  Required: – A bit of knowledge – Discipline – Tools  More benefits ? – Unit Testing
  • 55. BusinessSolutions SoftwareEngineering 24.02.2009  55 Unit Testing benefits  Higher product quality  Improved maintainability  Confidence – For changes, refactorings
  • 56. BusinessSolutions SoftwareEngineering 24.02.2009  56 Why unit testing  Improved quality but more than that  Easier to change, maintain the system  Better design „TDD isn't about testing because you're not thinking as a tester when doing TDD – you’re thinking as a designer.” SCOTT BELLWARE
  • 57. BusinessSolutions SoftwareEngineering 24.02.2009  57 The Tools  nUnit / MSTest Testing frameworks  RhinoMocks / Moq / TypeMock Mocking framework  Visual Studio/ReSharper/TestDriven.NET Integration/TestRunner  Visual Studio/NCover measures test coverage
  • 58. BusinessSolutions SoftwareEngineering 24.02.2009  58 nUnit - Startup  Create Test project assembly CodeBetter.Foundations.Tests  Add references nunit.framework.dll Rhino.Mocks.dll  Make internals visible (AssemblyInfo.cs) [assembly: InternalsVisibleTo(„CodeBetter.Foundations.Test s“)]
  • 59. BusinessSolutions SoftwareEngineering 24.02.2009  59 Configuration with Attributes using NUnit.Framework; [TestFixture] public class CarTests { [SetUp] public void SetUp() { //todo } [TearDown] public void TearDown() { //todo } [Test] public void SaveThrowsExceptionWhenInvalid() { //todo } [Test] public void SaveCallsDataAccessAndSetsId() { //todo } //more tests }
  • 60. BusinessSolutions SoftwareEngineering 24.02.2009  60 Example [Test] public void MathUtilityReturnsZeroWhenNoParameters() { Assert.AreEqual(0, MathUtility.Add()); } [Test] public void MathUtilityReturnsValueWhenPassedOneValue() { Assert.AreEqual(10, MathUtility.Add(10)); } [Test] public void MathUtilityReturnsValueWhenPassedMultipleValues() { Assert.AreEqual(29, MathUtility.Add(10,2,17)); } [Test] public void MathUtilityWrapsOnOverflow() { Assert.AreEqual(-2, MathUtility.Add(int.MaxValue, int.MaxValue)); }
  • 61. BusinessSolutions SoftwareEngineering 24.02.2009  61 Assert  Assert.IsFalse  Assert.IsTrue  Assert.IsNull  Assert.IsNotNull  Assert.AreSame  Assert.AreNotEqual  Assert.Greater  Assert.IsInstanceOfType  etc.
  • 62. BusinessSolutions SoftwareEngineering 24.02.2009  62 What is a Unit Test ?  Test/validate behaviour at a very granular level  One test for each behaviour  Quick to run
  • 63. BusinessSolutions SoftwareEngineering 24.02.2009  63 Mocking  Tested method often have dependencies car.Save()  database  Setup test database too complicated/slow  We want to test only if Save() interacts properly with DAL  DAL will be tested separately
  • 64. BusinessSolutions SoftwareEngineering 24.02.2009  64 Mocking  Manual Mocks  Limitations – Calls to our mock object not testable  Solution – Mock Framework: RhinoMocks
  • 65. BusinessSolutions SoftwareEngineering 24.02.2009  65 Mock – Test example [TestFixture] public class CarTest { [Test] public void SaveCarCallsUpdateWhenAlreadyExistingCar() { MockRepository mocks = new MockRepository(); IDataAccess dataAccess = mocks.CreateMock<IDataAccess>(); ObjectFactory.InjectStub(typeof(IDataAccess), dataAccess); Car car = new Car(); dataAccess.Update(car); mocks.ReplayAll(); car.Id = 32; car.Save(); mocks.VerifyAll(); ObjectFactory.ResetDefaults(); } }
  • 66. BusinessSolutions SoftwareEngineering 24.02.2009  66 Let it fail [Test] public void SaveCarCallsUpdateWhenAlreadyExistingCar() { MockRepository mocks = new MockRepository(); IDataAccess dataAccess = mocks.CreateMock<IDataAccess>(); ObjectFactory.InjectStub(typeof(IDataAccess), dataAccess); Car car = new Car(); dataAccess.Update(car); dataAccess.Update(car); mocks.ReplayAll(); car.Id = 32; car.Save(); mocks.VerifyAll(); ObjectFactory.ResetDefaults(); }
  • 67. BusinessSolutions SoftwareEngineering 24.02.2009  67 Check return values [Test] public void SaveCarCallsSaveWhenNew() { MockRepository mocks = new MockRepository(); IDataAccess dataAccess = mocks.CreateMock< IDataAccess>(); ObjectFactory.InjectStub(typeof(IDataAccess), dataAccess); private Car car = new Car(); Expect.Call(dataAccess.Save(car)).Return(389); mocks.ReplayAll(); car.Save(); mocks.VerifyAll(); Assert.AreEqual(389, car.Id); ObjectFactory.ResetDefaults(); }
  • 68. BusinessSolutions SoftwareEngineering 24.02.2009  68 Extract repetitive code [TestFixture] public class CarTest { private MockRepository _mocks; private IDataAccess _dataAccess; [SetUp] public void SetUp() { _mocks = new MockRepository(); _dataAccess = _mocks.CreateMock<IDataAccess>(); ObjectFactory.InjectStub(typeof(IDataAccess), _dataAccess); } [TearDown] public void TearDown() { _mocks.VerifyAll(); } ... }
  • 69. BusinessSolutions SoftwareEngineering 24.02.2009  69 Test for exceptions [TestFixture] public class CarTest { ... [Test, ExpectedException("CodeBetter.Foundations.PersistenceException")] public void SaveCarCallsSaveWhenNew() { Car car = new Car(); Expect.Call(_dataAccess.Save(car)).Return(0); _mocks.ReplayAll(); car.Save(); } }
  • 70. BusinessSolutions SoftwareEngineering 24.02.2009  70 TDD 1. Write test 2. Let test fail 3. Write code to make the test pass red  green  refactor
  • 71. BusinessSolutions SoftwareEngineering 24.02.2009  71 UI and Database Testing  ASP.NET Testing – Very tight coupled – Not easy/worth the effort to test  Data Access Layer Testing – Possible & recommended – Test-Database – Use SetUp and TearDown to create a known state
  • 73. BusinessSolutions SoftwareEngineering 24.02.2009  73 „With very few exceptions, I'd say that at this point that if you're writing ADO.Net code or SQL by hand, you're stealing money from your employer or client.” JEREMY D. MILLER
  • 74. BusinessSolutions SoftwareEngineering 24.02.2009  74 ORM Benefits  A lot less code => more maintainable system  Abstraction from data source (mapping)  Code becomes simpler, low impedance mismatch
  • 75. BusinessSolutions SoftwareEngineering 24.02.2009  75 NHibernate  Open-Source ORM framework  Complex   Completely transparent  – No base class, no decorator attributes – Unit testing of domain layer possible  Maps domain objects to database objects – Decouples code from specific DB implementation
  • 76. BusinessSolutions SoftwareEngineering 24.02.2009  76 NHibernate configuration <configuration> <configSections> <section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" /> </configSections> <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2"> <session-factory> <property name="hibernate.dialect"> NHibernate.Dialect.MsSql2005Dialect </property> <property name="hibernate.connection.provider"> NHibernate.Connection.DriverConnectionProvider </property> <property name="hibernate.connection.connection_string"> Server=SERVER;Initial Catalog=DB;User Id=USER;Password=PASSWORD; </property> <mapping assembly="CodeBetter.Foundations" /> </session-factory> </hibernate-configuration> </configuration>
  • 77. BusinessSolutions SoftwareEngineering 24.02.2009  77 NHibernate Mapping File <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="CodeBetter.Foundations" namespace="CodeBetter.Foundations"> <class name="Model" table="Models" lazy="true" proxy="Model"> <id name="Id" column="Id" type="int" access="field.lowercase- underscore"> <generator class="native" /> </id> <property name="Name" column="Name" type="string" not-null="true" length="64" /> <property name="Description" column="Description" type="string" not-null="true" /> <property name="Price" column="Price" type="double" not-null="true" /> </class> </hibernate-mapping>
  • 78. BusinessSolutions SoftwareEngineering 24.02.2009  78 Interacting with the database private static ISessionFactory _sessionFactory; public void Sample() { //Let's add a new car model Model model = new Model(); model.Name = "Hummbee"; model.Description = "Great handling, built-in GPS to always find your way back home, Hummbee2Hummbe(tm) communication"; model.Price = 50000.00; ISession session = _sessionFactory.OpenSession(); session.Save(model); //Let's discount the x149 model IQuery query = session.CreateQuery("from Model model where model.Name = ?"); Model model = query.SetString(0, "X149").UniqueResult<Model>(); model.Price -= 5000; ISession session = _sessionFactory.OpenSession(); session.Update(model); }
  • 79. BusinessSolutions SoftwareEngineering 24.02.2009  79 Relationships public SalesPerson SalesPerson { get; set; } <many-to-one name="SalesPerson" class="SalesPerson" column="SalesPersonId" not-null="true"/>
  • 80. BusinessSolutions SoftwareEngineering 24.02.2009  80 The other side of the relationship private IList<Sale> _sales; public IList<Sale> Sales { get { return _sales; } } <bag name="Sales" access="field.lowercase-underscore" table="Sales" inverse="true" cascade="all"> <key column="SalesPersonId" /> <one-to-many class="Sale" /> </bag>
  • 81. BusinessSolutions SoftwareEngineering 24.02.2009  81 Querying string lastName = "allen"; ISession session = _sessionFactory.OpenSession(); //retrieve a salesperson by last name IQuery query = s.CreateQuery("from SalesPerson p where p.LastName = 'allen'"); SalesPerson p = query.UniqueResult<SalesPerson>(); //same as above but in 1 line, and with the last name as a variable SalesPerson p = session.CreateQuery("from SalesPerson p where p.LastName = ?").SetString(0, lastName).UniqueResult<SalesPerson>(); //people with few sales IList<SalesPerson> slackers = session.CreateQuery("from SalesPerson person where size(person.Sales) < 5").List<SalesPerson>();
  • 82. BusinessSolutions SoftwareEngineering 24.02.2009  82 Lazy Loading  By default, collections are lazy loaded e.g. SalesPerson.Sales  lazy="false"  Session.Load<T>(id) loads Proxy
  • 83. BusinessSolutions SoftwareEngineering 24.02.2009  83 Lazy Loading Sale sale = new Sale(session.Load<Model>(1), DateTime.Now, 46000.00); salesPerson.AddSales(sale); session.SaveOrUpdate(salesPerson);
  • 85. BusinessSolutions SoftwareEngineering 24.02.2009  85 Wrapping it up  The most flexible solution is the simplest. – YAGNI, DRY, KISS and explicitness.  Coupling is unavoidable, but must be minimized. – The more dependencies you have, the harder your code is to change. – Unit Tests are the path to mastering low-coupling. Badly coupled code will be impossible to test.
  • 86. BusinessSolutions SoftwareEngineering 24.02.2009  86 Wrapping it up  Higher quality should be good enough reason to write tests, but, there are better reasons. – Testing helps you identify bad coupling. – Testing helps you find awkwardness in your API. – Testing helps you document behavior and expectations. – Testing lets you make small and radical changes with far greater confidence and far less risk.
  • 87. BusinessSolutions SoftwareEngineering 24.02.2009  87 Wrapping it up  It's possible to build successful software without being Agile - but it's far less likely and a lot less fun. – ongoing customer collaboration – iterative development – No signed off specifications before starting to develop
  • 88. BusinessSolutions SoftwareEngineering 24.02.2009  88 References  Foundations of Programming, Karl Seguin http://codebetter.com/blogs/karlseguin/archive/2008 /06/24/foundations-of-programming-ebook.aspx with additional topics – Back to Basics: Memory – Back to Basics: Exceptions – Back to Basics: Proxy This and Proxy That
  • 89. BusinessSolutions SoftwareEngineering 24.02.2009  89 Links  http://www.codebetter.com  http://structuremap.sourceforge.net  http://www.nunit.org  http://ayende.com/projects/rhino-mocks.aspx  http://www.nhibernate.org