Software Architect Conference 2012 November 19, 2012Posted by codinglifestyle in Architecture, ASP.NET, CodeProject, Parallelism.
Tags: architect, requirements, software architecture, software design, technical debt
I was fortunate enough to have the opportunity to attend the Software Architect Conference this year in London. This is the same group which puts on DevWeek. It was short and sweet, just 2 days without the additional sessions before and after. Often with the daily grind you simply don’t have the time or inclination to challenge yourself with the sort of material presented at these conferences. This is what makes them unique, for a few precious days you are free of distractions to consider how and why we do what we do. I certainly found it useful and some of the speakers where truly impressive. While the technology we use continues to change at the speed of light, the great thing about software architecture is many of the basic principals of building a stable, well-engineered system haven’t changed since medieval times.
Theme: 21st century architects should aspire to be like medieval “master builders”
- 7 years apprentice, many years to master, administers the project, deals with client, but still a master mason
- Keep coding – credibility with team, mitigates ivory tower
20th century software architects
- Stepped away from the code
- Analysis paralysis
- Ivory Tower syndrome
- Enterprise Architecture Group – not sustainable, disconnected
- CV driven development – ego and fun over needs and requirements
- Going “Post-technical” – no longer involved in programming
Software Architecture summed up
- Create a shared vision – get everyone to move in the same direction
Architectural lessons learnt lost in Agile – baby out with the bath water
- It is a myth that there is a conflict between good software architecture and agile
What we do
- Requirements and constraints
- Evaluate and vet technology
- Design software
- Architectural evaluation
- Technical ownership
- True team leadership is collaborative / mentoring
- Big picture: Just enough architecture to provide vision enough to move forward
Architectural definition defines 3 things
- What are the structural elements of the system?
- How are they related to each other?
- What are the underlying principles and rationale to the previous 2 questions?
- Decompose a program into smaller pieces to help achieve modifiability.
- Single threaded sequential execution
- Still procedural: single thread of control
- Decouples activities from main process but still procedural
- Shared data must be immutable or copied
- Some people, when confronted with a problem, think, “I know, I’ll use threads,” and then two they hav erpoblesms.
Event based, Implicit Invocation
- The components are modules whose interfaces provide both a collection of procedures and a set of events
- Extensible / free plumbing
- Inversion of control (not dependency inversion)
- Asynchronous way to interact reliably
- Instead of threads and shared memory use process independent code and message passing
- Regardless of interactions and coupling between different parts of a system, there is a need to develop and evolve them independently
- Each layer having a separate and distinct responsibility following a reasoned and clear separation of concerns
- Often “partitioned” but not true layers due to cross references which sneak in
Alternate Layers – spherical
- Core – domain model
- Inner crust – services wrapped around core
- Outer crust – wrapped external dependencies
Micro-kernel / Plug-in
- Small hub with everything plugged in
- Separates a minimal functional core from extended functionality and customer-specific parts
- DB and the like
- Procedures secondary, data is king!
- Maintain all data in a central repository shared be all functional components of the data-driven application and let the availability, quality, and state of that data trigger and coordinate the control flow of the application logic.
Pipes & Filters
- Divide the application’s task into several self-contained data processing steps and connect these steps to a data processing pipeline via intermediate data buffers.
- Process & queue → process & queue → process & queue
The Architecture of an Asynchronous Application
- Heavy focus on messaging throughout talk
- Guaranteed delivery at a cost
- Reliable and scalable
- 1 : n
- Round robin
- Publish / Subscribe
- Idempotency – will doing something twice change data / state?
- Poison message – situation where a message keeps being redelivered (perhaps because an exception is thrown before an ack is returned to queue)
- MSMQ – MS specific (personally found it easy enough to use)
- IBM MQ
- RabbitMQ – multiplatform, Multilanguage binding. Mentioned in numerous talks and focus of talk.
SignalR – interesting client-side messaging platform could be a more powerful model than using web services on the client
- install-package SignalR with NuGet
- Picks best available connection method
- Push from server to client
- Broadcast to all or to a specific client
Async with C# 5
- This talk is largely about Tasks and iterates through several examples of an application trying various asynchronous styles. The point is to try to get a minimal syntax such that an asynchronous application can be written is the same number of lines as a procedural program.
Context – must know the identity of which thread is executing. Critical in UIs and error handling
- SynchronizationContext class can revert thread context to calling thread (as can several other methods such as Invoke)
Tasks – a piece of asynchronous functionality
- Uses continuations to handle results
Async keyword – marks a function to allow use of the await keyword. Must return void or a Task.
private async void CalculatePi()
// Create the task which runs asynchronously.
Task<double> result = CalculatePiAsync();
// Calls the method asynchronously.
// Display the result.
textBox1.Text += result;
- Putting a try/catch around this an the compiler will ensure that the error is rethrown in the correct context.
- Automatic use of thread pool which measures throughput to scale number of running threads up or down, as appropriate
Progress / Cancellation Features
Can launch a collection of classes and then use different operation types such as
- var task = Task.WhenAny(tasks);
- which returns when the first task completes. Or use Task.WhenAll to wait for all tasks.
- WCF can generate the async methods to use tasks when adding Service References -> Advanced.
- Kevlin Henny, author 97 Things Every Programmer Should Know and Pattern Oriented SW Arch
- While listening to requirements we often stop listening while jumping ahead to solutions
- Killer question when cutting through nefarious design agendas: “What problem does this solve?”
- Patterns often misapplied – using a hammer to drive a screw leading to a pattern zoo
- Composing a solution to a problem rather than analysis to understand the problem
- Many to many relationships don’t need to be normalized (they model the real world)
- Describing is not the same a prescribing
A model is an abstraction of a point of view for a purpose
- Good – omits irrelevant detail
- Bad – omits necessary detail
RM-ODP: reference model using viewpoints a way of looking at a system / environment
- Enterprise – What does it do for the business?
- Information – What does it need to know?
- Computational – Decomposition into parts and responsibilities
- Engineering – Relationship of parts
- Technology – How will we build it?
Use inverted pyramid style to place most important detail at the top. Move post-condition next to pre-condition. Sequence, containing detail about how you accomplish the steps in-between pre and post at bottom as only interest to implementers.
- Sequence – lots of juicy detail but actually least important from an architecture point of view
Traditional Connextra form
- As a <role>,
- I want <goal/desire>
So that <benefit>
- As an Account Holder
- I want to withdraw cash from an ATM
- So that I can get money when the bank is closed
Dan North scenario form
- Given <a context>
- When <a particular event occurs>
Then <an outcome is expected>
- Scenario 1: Account has sufficient funds
- Given the account balance is \$100
- And the card is valid
- And the machine contains enough money
- When the Account Holder requests \$20
- Then the ATM should dispense \$20
- And the account balance should be \$80
- And the card should be returned
Problems with the Use Case / User Story approach
- Observations are always made through a filter or world-view
- Until told what to observe you don’t know what you’ll get. In that case, is it even relevant?
- Use Case Diagrams neglect to notice they are fundamentally text/stories
Context Diagrams – shows the world and relationships around the system (UML actors)
- Litmus test: what industry does the diagram apply to?
- Not a technical decomposition
You’re an engineer planning to build a bridge across a river. So you visit the site. Standing on one bank of the river, you look at the surrounding land, and at the river traffic. You feel how exposed the place is, and how hard the wind is blowing and how fast the river is running. You look at the bank and wonder what faults a geological survey will show up in the rocky terrain. You picture to yourself the bridge that you are going to build. (Software Requirements & Specifications: “The Problem Context”)
- An analyst trying to understand a software development problem must go through the same process as the bridge engineer. He starts by examining the various problem domains in the application domain. These domains form the context into which the planned Machine must fit. Then he imagines how the Machine will fit into this context. And then he constructs a context diagram showing his vision of the problem context with the Machine installed in it.
- Problem Frame approach – describe a problem in diagrams
- Use centric – visualization and manipulation of objects in a domain
- Datacentric – integrity persisting objects
- Computational centric – focus on transforming objects
- In summary: move from ignorance / assumptions → knowledge gathered from multiple points of view
A Team, A System, Some Legacy… and you
- Legacy System – so valuable it can’t be turned off (and it’s paid for!)
- Be aware a legacy system often comes with a legacy team engrained in their own methods
Being late to the party
- Software architecture often seems valuable only once things have gone wrong.
- Architects often join existing projects with to help improve difficult situations
- Often a real sense of urgency to “improve”
- Avoid distancing self to ivory tower and likewise avoid digging in thus losing big picture focus
- Software architecture techniques offer a huge value for older or troubled projects. Especially techniques to understand where you are and with whom
Stage 1: Understand
- See gathering requirements for perspectives of end user, business management, IT Managers, development, and support
Automated analysis tools
- NDepend, Lattix, Stucture 101, Sonar
- Dependency analysis
Monitor / Measure
Leverage existing production metrics
- Oracle Enterprise Manager
- Implementation metrics
- Stakeholder opinions
Systems Quality Assessment
- Context and stakeholder requirements
- Functional and deployment views
- Monitor and measure
- Automated analysis
- ATAM – architectural trade off analysis method
- LAAAM – Lightweight architectural assessment method- more practical
TARA – tiny architectural review approach (recommended)
- Define notation / terminology
Break up system to different viewpoints
- Deployment – systems / services
- Ops – run, controlled, roll-back
- Focus on essentials for target audience
- System context and requirements
- Functionality and deployment views
- Improve Analysis
- Requirements Assessment
- Identity and report
- Conclusion for sponsor
- Deliver findings and recommendations
Stage 2: Improve
- Team must be involved or rocketing risk affecting morale, confidence, competence
Choices based on risk
- Assess -> Prioritize -> Analyse -> Mitigate
Engage in Production
- Reality check
- Monitoring, stats, and incidence management
- Biz man, IT man, support
Tame the Support Burden
- Drain on development
- Support team can offset this
- Avoid “over the wall” mentality
Continuous Integration and Deployment
- Start simple
- Increased efficiency and reliability
- Unit test + coverage, regression tests
Safe step evolution
- Control risk
- Wrap with tests
Stay coding – but if a pure architect stay off the critical path
- Beware ROI of your coding skills vs. architect’s skills
- Refactor, write unit tests, address warnings
Define the future
- Good for the team
- Clear, credible system architecture for the medium term (1-2 years)
- Beware: timing and predictions
- As an evolving program is continually changed, its complexity (reflecting deteriorating structure) increases unless work is done to maintain or reduce it
- Technical Debt is a metaphor developed by Ward Cunningham to help us think about the above statement and choices we make about the work required to maintain a system
- Like a financial debt, the technical debt incurs interest payments, which comes in the form of the extra effort that we have to do in future development because of the quick and dirty design choice. We can choose to continue paying the interest, or we can pay down the principal by refactoring the quick and dirty design into a better design
- Sometimes, upon reflection, it is better to pay interest. But are we trapped paying so much interest we can never get ahead?
What is the language of debt?
- Amortise, repayment, balance, write off, restructure, asset, interest, default, credit rating, liability, principal, load, runaway, loan, consolidation, spiralling, value
- Shipping first time code is like going into debt. A little debt can speed delivery so long as it is paid back promptly with a rewrite
- The danger is ignoring or not paying back the debt (compound interest!)
- Rebuttal: A mess is not a technical debt. A mess is just a mess.
- Counter response: The useful distinction isn’t between debt or non-debt, but between prudent and reckless debt.
There is also a difference between deliberate debt and inadvertent debt.
- There is little excuse for introducing reckless debt
- Awareness of technical debt is the responsibility of all roles
- Consideration of debt must involve practice and process
Management of technical debt must account for business value
Perfection isn’t possible, but understanding the ideal is useful
Books, People, and Topics of Note
- Simon Brown – www.codingarchitecture.com
- Alan Holub – www.holub.com
- Kevlin Henney – Pattern Oriented Software Architecture
- Grady Booch – architecture vs. design
- Linda Rising
- George Fairbanks – Just Enough Software Architecture
- Roy Osherove – Notes to a Software Team Leader
- Top 10 Traits of a Rockstar Software Developer
- Becoming a Technical Leader – Gerald Weinberg
- 101 Things I Learned in Architecture School
- Architecting Enterprise Solutions
- Software Architecture – Perspectives of an Emerging Discipline
- Software Requirements and Specification – Michael Jackson
- Problem Frames – Michael Jackson
- 12 Essential Skills For SW Arch
- Refactoring to Patterns
- Managing Software Debt
- Modernizing Legacy Systems
- Working Effectively with Legacy Code
- Growing Object-Oriented Software, Guided by Tests
- Backbone.js – model / view extension with events
- Parasoft Jtest smoke test
- Selenium automation UI test
- RabbitMQ – client side messaging queue
- LightStreamer / SignalIR – web sockets for client (stop gap for HTML5?)