As a noun architecture can be summarised as being about structure
and is about the decomposition of a product into
a collection of components and interactions.
Software Architecture for Developers by @simonbrown
The assurance that a product, service, or system meets the needs of the customer and other identified stakeholders
Organizations give disproportionate weight to trivial issues
by Cyril Northcote Parkinson
more at bikeshed.com
What to choose: Iesi.Collections.ISet
,
System.Collections.Generic.ISet
or
NPOI.Util.Collections.ISet
?
A fail-fast system is designed to immediately report any failure or condition that is likely to lead to failure
First we'll solve the "that works" part of the problem, then we'll solve the "clean code" part
Architecture Driven DevelopmentSolve "clean code" first, then scramble around trying to integrate into the design the things you learn as you solve the "that works" problem
TDD by examples by @kentbeckFrom Roslyn CTP
public object ReturnNullReferenceType() { return null; }
return null;
Func<StatementSyntax, bool> returnNullStatement = PredicateBuilder .True<StatementSyntax>() // all return statements .And(s => s is ReturnStatementSyntax) // with expression .And(s => (s as ReturnStatementSyntax).Expression != null) // with expression "null" .And(s => (s as ReturnStatementSyntax).Expression.Kind == SyntaxKind.NullLiteralExpression) .Compile();
return default(T);
Where T
is reference type
ExpressionSyntax expressionSyntax = (statement as ReturnStatementSyntax).Expression; ISemanticModel semanticModel = await semanticModelAsync; return expressionSyntax != null && (semanticModel.GetTypeInfo(expressionSyntax).Type == null || semanticModel.GetTypeInfo(expressionSyntax).Type.IsReferenceType);
IEnumerable<T>
or IQuerable<T>
new
in constructor[Attribute]
compositionDateTime.Now
and DateTime.Today
Using System.Reflection
[Test, Combinatorial] public void TestReferencesIntersection( [ValueSource("Assemblies")] Assembly leftAssembly, [ValueSource("Assemblies")] Assembly rightAssembly) { if (leftAssembly == rightAssembly) return; var rightReferences = FilterOutAssemblies(rightAssembly); var leftReferences = FilterOutAssemblies(leftAssembly); Assert.That(leftReferences.Intersect(rightReferences), Is.Not.Null.And.Empty); } private static IEnumerable<string> FilterOutAssemblies(Assembly source) { return new HashSet<string>(source .GetReferencedAssemblies() .Where(assembly => assembly.Name != @"mscorlib" && assembly.Name != @"Microsoft.CSharp" && !assembly.Name.StartsWith(@"System") && !assembly.Name.StartsWith(@"AutoMapper") && !assembly.Name.StartsWith(@"nCrunch.TestRuntime") && !assembly.Name.StartsWith(@"PostSharp")) .Select(assembly => assembly.Name)); }
dynamic
, async
/await
Capturing Human Intelligence
[Test, Timeout(2000)] // <-- brittle unit tests!!! [Description("Find collinear points among 1000 random distinct points")] public void Timing_FindCollinearPoints1kRandomDistinctPoints_ExpectToFinishIn2Seconds() { /* Actual test */ }
virtual
/override
Equals()
, GetHashCode()
, CompareTo()
[Test, Timeout(2000)] [Description("Compare complexity of two solutions of sizes 64 and 256 to be less then 5.4")] public void Timing_CompareComplexityOfTwoSolution64and256_ExpectToInRange() { var partialMockedProblem64 = mockRepository.PartialMock<AlgorithmImpl>(/* initialize problem size */); var partialMockedProblem256 = mockRepository.PartialMock<AlgorithmImpl>(/* initialize problem size */); /* and so on… */ partialMockedProblem64 .Expect(m => m.DoCalculations(/* arguments */)) .CallOriginalMethod(OriginalCallOptions.CreateExpectation) .WhenCalled(invok => nTimesDoCalculationsCalledProblem64++) .Repeat.AtLeastOnce(); /* and so on… */ mockRepository.ReplayAll(); /* Act */ /* Assert */ mockRepository.VerifyAll(); var cmp64 = nTimesDoCalculationsCalledProblem64 * Math.Log(nTimesDoCalculationsCalledProblem64); var cmp256 = nTimesDoCalculationsCalledProblem256 * Math.Log(nTimesDoCalculationsCalledProblem256); Assert.That(cmp256 / cmp64 < 5.4); /* ask BA with PhD why? :) */ /* and so on… */ }
Check constraints
Serialize state for runtime
ScalarConstraint
and
ReferentialConstraint
class with typical code issues
public class Customer { // This property is defined as expected public virtual int Id { get; set; } // without `virtual` keyword PostSharp will generate compile-time error message // otherwise NHiberante will generate exception during run-time public /*virtual*/ string Name { get; set; } // Both getter/setter are required to be public internal virtual string Description { get; private set; } }
Validate that all properties are public
, virtual
with getter and setter
[Serializable] [MulticastAttributeUsage(MulticastTargets.Property)] public class VirtualKeywordRequiredForInstancePropertiesAttribute : ScalarConstraint { // Validation happens only at post-compile phase public override void ValidateCode(object target) { var propertyInfo = (PropertyInfo)target; var targetType = propertyInfo.DeclaringType; if (targetType != null) { // check that property is public, virtual with getter and setter var virtualInstanceProperty = targetType .GetProperties(BindingFlags.Public | BindingFlags.Instance) .Where(propInfo => propInfo.CanRead & propertyInfo.CanWrite) .Where(propInfo => propInfo.GetGetMethod().IsVirtual) .Where(propInfo => propInfo.GetSetMethod().IsVirtual) .SingleOrDefault(propInfo => propInfo == propertyInfo); // generate compile time error if (virtualInstanceProperty == null) { Message.Write(MessageLocation.Of(targetType), SeverityType.Error, "998", "Property '{0}' in Entity class {1} show be public, virtual with both getter and setter", propertyInfo.Name, targetType.FullName); } } } }
// Multicast aspect to all properties of classes in namespace
[assembly: VirtualKeywordRequiredForInstanceProperties(
AttributeTargetTypes = "CodeSmells.FakeDataAccessLibrary.Entity.*",
AttributeTargetElements = MulticastTargets.Property)]
Error generated by PostSharp aspect validation
If you perceive that there are four possible ways in which something can go wrong,
and circumvent these, then a fifth way, unprepared for, will promptly develop
by Edward Aloysius Murphy
Use a spacebar or arrow keys to navigate