Software Architecture: How Much Design?

Post on 10-May-2015

119 views 3 download

Tags:

description

Large software projects cannot be built without some amount of analysis and design. But not all parts of the system require the same amount of design. Some may not require any upfront design at all. Others require a few minutes of architecture discussion; some require weeks of analysis, documents and review. A balance is necessary: too much design and you're delaying the project; too little and you will add technical debt which you'll have to pay in future rewrites and painful maintaining. How do we decide when design is needed and how much of it is needed? How do other Agile projects do it? In this talk I discuss what the Agile literature has to say about architecture and how we can answer this question.

Transcript of Software Architecture: How Much Design?

How much design?

Òscar Vilaplana Paylogic, winter 2013

How much talk?

Know How Much & What It Means

What matters

Love the risks

Risks of Models

Architecture-Evident Code

What matters

-Paul Clemens

“The software architecture of a computing system is the set of structures needed to

reason about the system, which comprise software elements, relations among them, and

properties of both.”

Issues

Organization of a system as a composition of components

Global control structures

Protocols

Physical distribution

Scaling, performance

Evolution

Design alternatives

What Counts

Macroscopic parts of the design

Everything else is cover on detailed designs.

Not limited to the biggest parts in the system.

e.g. the naming pattern of a method may be architecturally significant.

e.g. prohibit threads, set time duration limitations on methods, require jobs to be scheduled…

The Chain of Intentionality

Chain from high-level intentions or decisions to low-level details.

Most details left open to reasonable implementation, but not all!

Why is it important?

Skeleton of the system

Influence on quality

Mismatch architecture/functionality: difficult to develop.

Imposes constraints

easy/possible for the system to evolve in a certain way

impossible to evolve in other ways

Constraints?

Embody judgement: guide other engineers to acceptable solutions without transferring all knowledge of the domain.

Conceptual integrity. Reduce needless creativity.

Reduce complexity

Understand runtime behavior

-Frederik P. Brooks

Conceptual integrity of a system is an important goal of system design.

A single good idea consistently applied is better than several brilliant ideas scattered

across a system.

When is it important?

Small solution space, or it’s hard to design any acceptable solution.

High failure risk.

Difficult quality attributes, such as meeting a very high performance requirement.

New domain, even if it’s just new to you.

Product lines, in which all products must share a common architecture.

When is it important?

How bad would it be to get the architecture wrong?

Basic approaches

Ignore

Embrace

Hoist

Architecture-indifferent design

Degrades.

No shared architectural visiaon.

Increasing complexity.

Architecture-focused design

Seeks architectural solutions.

Entails reasoning.

Uses abstractions, views.

Architecture hoisting

Choose a suitable architecture.

The architecture does the work for you.

Example

(made up)

Requirement

The system must respond to requests within 50ms.

Architecture-indifferent

Reuse the distributed architecture from another system.

If the communication is too slow:

Try to make the code more efficient.

Change the architecture.

Architecture-focused

Analyze the rest of the requirements of the system.

Design an architecture that is compatible with them.

Measure: Prototype, stress test, profile.

Architecture hoisting

How can the architecture ensure that a 50ms response is always achievable?

Peak demand times? Can we get additional processing from the cloud?

Example

(real)

Example: Queue

Handle 10.000+ users per second.

Stability: keep working if a few (but not all) servers die.

Architecture: decentralized, identical nodes.

Lower level: distributed synchronization.

Benefits: easy scale up with load. Ensure fast response.

Fairness with waiting times (within limits).

Accepted tradeoffs: difficult to estimate waiting time, difficult to develop and test, limited fairness.

Example: Queue, Improved

Keep working even if ALL servers die (with reduced functionality).

Recover from errors, don’t fail to the customers.

Architecture: client-server

Tradeoffs: the client becomes a SPF: requires additional testing, protective coding.

Recap

Software architecture deals with the large-scale decisions and macroscopic elements. These decisions have a deep impact into the code.

The archictecture choices are important because the architecture asks as a skeleton of the system and influences all its attributes: if the architecture is suitable for the desired features, it will be easier to build them; if it’s unsuitable, you will struggle.

Architecture is just one of many things that require attention. It’s helpful to know ho much attention to pay to it.

Architecture is important enough to understand and choose deliberately.

Software Architecture

Deals with the large-scale decisions and macroscopic elements.

The decisions have a deep impact into the code.

The archictecture choices are important.

Architecture acts as a skeleton of the system and influences all its attributes.

Architecture is important enough to understand and choose deliberately.

How much?

Love the risks

The concept of failure is central to

the design process,

and it is by thinking in terms of

obviating failure

that successful designs are achieved.

Failure considerations

and proactive failure analysis

are essential for achieving success.

It is precisely

when such considerations and analyses are

incorrect or incomplete

that design errors are introduced

and actual failures occur.

- Petroski, Henry Design Paradigms: Case Histories of Error and Judgment in Engineering.

Common approaches

No front-up design

Yardstick

Upfront documentation

Ad-hoc

Risk-driven

No up-front design

Just write code.

Design happens together with coding.

Impractical when failure risks are high.

Yardstick

Define percentages of time that should be spent an design, coding, integration…

Can help plan architecture effort

Does not help you choose techniques.

Upfront documentation

Choose appropriate design techiques.

Write a design documentation upfront.

Impractical when failure risks are low.

Ad-hoc

React to the project needs.

Decide on the spot how much design to do.

Subjective.

No enduring lessons.

Risk-driven

Risks are considered as seriously as features.

Identify and prioritize risks.

Select and apply techniques.

Evaluate risk reduction.

Are you risk-driven?

What are your primary failure risks and corresponding engineering techniques?

What are risks?

What are risks?

risk = perceived probability of failure × perceived impact

Risk descriptions

Actionable.

Testable failure scenarios.

Engineering Risks

Analysis

Design

Implementation

Project Management Risks

Schedules

Sequencing of work

Delivery

Team size

Shared vocabulary

Product may not understand why something doesn’t work.

They will understand the risk of its failure.

Engineering helps Product understand.

Reverse true.

Treating risks with agility

1. Identify risks.

2. Evaluate mitigation.

3. Write remaining risks in testable form.

4. Prioritize risks together with features.

Identifying risks

Qualities difficult to achieve.

Incomplete requirements?

Quality Attribute Workshop

Taxonomy-Based Questionnaire

Accept risks.

Prototypical risks

Risks inherent in the domain.

Checklist.

Know them.

Notice when deviating from the norm.

Prioritizing risks

Priority to stakeholders.

Perceived difficulty by developers.

Reduce Risks

Risk reduction process

Explicit.

Repeatable.

Choose technique based on risk.

Risk cannot be avoided.

Understand the problem.

Models: Analogic vs Analytic

Analogic: each element has an analogue in the domain.

Analytic: direct computational analysis.

Choose model based on risk

Understanding relationship between domain entities: Analogic.

Calculate response time distributions: Analytic.

Stop!

Know when to stop

effort ∝ risk

Desing risky parts

Subjective evaluation

Evolutionary vs Planned

Planned design

Detail before construction.

Not sure it can be built.

Shared architecture.

Minimal planned design

Plan to address biggest risks

Evolve rest

Evolutionary design

Grows with system.

Refactoring.

Test-driven design.

Continuous Integration.

Plan or Evolve?

Planning

Global properties

Avoid dead ends

Team coordination

Easier to make mistakes

Evolutionary

See it working earlier.

Identify mistakes.

Agile.

Fun with Models

Focus on risks

Trade-off architecture risks vs time, acceptance…

Map risks and techniques.

Understand

Why did you take this decision?

Why did you follow this process?

Distribute architecture skills

Engineering concern!

Efficient communication.

Answer questions, relate them to architecture models.

Small code details can be architecturally significant.

Stick to architecture vs raise flag for change.

Architect doesn’t compensate for developer knowledge.

Choices

Design involves tradeoffs.

Align tradeoffs align with quality attribute priorities.

Follow pattern that:

Helps understand reasoning

Can be evaluated to check if decisions align with priorities

X is a priority, so we chose design Y

and accepted downside Z

Risks of Big Design Up Front

Unnecessary documentation.

Coding starts → new risks or requirements found → documentation outdated.

!

Address critical risks.

Prototype / implement.

Instead:

Risks of Top-Down Design

Lower-level patterns ignored.

Incompatibility top-level / lower levels.

Lost oportunity for great solutions due to premature top-level decisions.

Example

Risks

Extensibility supporting new use cases part of the domain requires changing the API.

Knowledgeunderstanding the domain is not enough to understand the API.

Discoverability clients need to implement API- or domain- logic in order to use the API.

Risks, Addressed

Extensibility, KnowledgeChoice of resources and actions: follow domain, don’t restrict to use cases.

Discoverability Consistency of resources, representations, actions.Machine- (and human-) readable documentation for each entry point.

Tradeoffs

Efficiency

Interface segregation.

–Robert C. Martin

Many client specific interfaces are better than one general purpose interface

Risks

Extensibility supporting new use cases part of the domain requires changing the API.

Knowledgeunderstanding the domain is not enough to understand the API.

Discoverability clients need to implement API- or domain- logic in order to use the API.

Tradeoffs

Efficiency

Interface segregation.

Risks

Extensibility: Adding a custom API for a client (e.g for efficiency purposes) requires rewriting the business logic.

Communication

HTTP APIHTTP interface

PTAPython simple types interface

Paylogic Core InterfaceInterface to the core, guarantee business rules

Paylogic Core

Communication’

Fast Frontoffice HTTP APIPython interface that provides an efficient HTTP interface for the Frontoffice

PTA

Paylogic Core Interface

Paylogic Core

Communication’

Frontoffice HTTP LayerSimple HTTP layer

Fast Frontoffice APIPython interface that provides an efficient API for the Frontoffice

Paylogic Core Interface

Paylogic Core

Remaining Challenges

Estimating Risks

Unforeseen risks (checklists help).

Risk priority.

Evaluating Alternatives

Costly.

Balance of detail:

Enough detail to represent usefulness.

Work required.

Reusability of models

Not always possible.

Safely ignored details may be important when reusing.

Issues Spanning Other Teams

Dilemma:

Solve problem in Engineering, or

Buy tool for Customer Support to solve on their own.

Risks of Models

Solving Problems

Sometimes abstractions are needed.

Sometimes they aren’t.

Good choice: efficiency + good results!

Abstractions

Size, complexity.

Focus on essence.

Reason about system qualities.

-George E. P. Box

All models are wrong,

but some are useful.

Reasoning

One model, different purposes.

Amplify reasoning.

Standards: spot errors.

Question first!

What to ask?

Details

Abstraction level

Risks of Model Everything

Wasted effort.

Analysis paralysis.

Not every project needs models

Models help solve problems and mitigate risks.

Some problems are best solved with models.

Other problems are best solved directly.

Don’t Blindly Model Thoroughly

Is there a reason?

Is there a risk?

Code first?

Reveal risks.

Prototype, test, measure.

Models

Domain: Truths.

Design: System. Commitments (incomplete)

Code: Implementation structure. Commitments (complete).

Business: What the business does, why. Goals.

Common objections

Already know the domain.

Too simple.

Irrelevant for architecture.

Someone else’s job.

Learn by coding.

Analysis paralysis.

Common objections

Already know the domain: Details!

Too simple: Details!

Irrelevant for architecture: How do you know!

Someone else’s job: Your insight!

Learn by coding: Impractical!

Analysis paralysis: Indeed, but <next slide>!

Avoid Paralysis

Begin with questions

…about failure risks!

Decide ahead depth and breadth

Know when to stop.

Architecture Evident

Code

Code-Model Gap

Abstraction

Commitments

Intensional elements

Work Through the Gap

Understand both the architecture models and the code.

Keep models and code in sync.

Write architecture-evident code.

When to update the model?

Architecture Evident Code

Code: solution.

Decisions?

Embed architectural intent.

Go beyond “it works”.

Why?

Evolution.

Maintainability.

Developer efficiency.

Lower documentation burden.

Easy to get started.

Hints

Intent: cancel a basket.

Not evident: db.query(‘update ord_orders where…’)

Evident: pta.basket.cancel(…). As in the domain:

Basket resource.

Cancel operation.

Model In Code

Types and relationships of the domain are still valid in the code.

Makes sense in the domain: it makes sense in the code.

Easier to allocate responsibilities.

Easier to learn about the domain by reading the code.

Conclusion

Care About

Architecture.

Risks.

Right measure.

Re-evaluate.

Sync model and code.

Make model evident.

Thanks!