0% found this document useful (0 votes)
3 views

notesv2

The document outlines various software architecture and design principles, focusing on quality attributes such as security, availability, and maintainability. It discusses different programming paradigms including procedural, object-oriented, and functional programming, highlighting their respective advantages and disadvantages. Additionally, it emphasizes the importance of concepts like separation of concerns, low coupling, and design anti-patterns in creating robust software systems.

Uploaded by

Suresh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

notesv2

The document outlines various software architecture and design principles, focusing on quality attributes such as security, availability, and maintainability. It discusses different programming paradigms including procedural, object-oriented, and functional programming, highlighting their respective advantages and disadvantages. Additionally, it emphasizes the importance of concepts like separation of concerns, low coupling, and design anti-patterns in creating robust software systems.

Uploaded by

Suresh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 70

Mubarak

» Skan.ai - chief Architect


» Ai.robotics - chief Architect
» Genpact - solution Architect
» Welldoc - chief Architect
» Microsoft
» Mercedes
» Siemens
» Honeywell Mubarak
Agenda

• Cyclomatic Complexity • Expectations

• Cohesion • Years of Exp

• Coupling • Technology stack

• Composition • Domain
Architecture vs Design
Quality Tatctics Metrics

# availability @ Authentication $ Latency


# security @ Authorization $ response time
# Reliability @ Encryption
# Robustness
# scalability @ Modularity
# usability @ unit test
# maintainability @ Low coupling
# performance @ reusability
# Portability @ readability
# Interoperability @ doc

@ sharding
@ caching
@ parallel
@ lazy loading
@ polling
System Quality

Collect Choose
Quality
Tactics/ Approach
Requirements
(Architecture)

Knows

Technology
Domain
Architectural patterns
Principles
Architectural Anti patterns
Reference Architecture
Code Maintainability

Understand Create
Requirements Code Skeleton
(Design)

Knows
Technology Code Design
Domain Low level design
proc, OO, fun Module Design
OO Design patterns Class Design
Fun Design patterns Implementation Design
Design Principles
Design Anti patterns
Proc vs OO
Proc OO Fun

Performance - - +++

Language C, py, js, java py, java, js Scala, py, js, java

Security - - -

Time to develop ++ -- +

Learning curve Easy Difficult Medium

Manage code
--- +++ +
complexity
Quality Approach

• Security (trust) • Parallel

• Availability • Caching

• Scalability • GC

• Performance • Lazy loading

• Maintainability • Load Balancing

• Reliability(trust) • Unit Test

• Robustness (rugud) • Monitoring and Alerts

• Portability • Doc

• Usability • Transaction

• Interoperability •
Procedural Prog OO Prog
(tree)
(Lego)

P1 classA
Invoice Kst
O CO

P2 P3 classC
Kst
classB O C
Invoice C
O

P4 P5 P6
Cst
classD classE Gst
O
O
Functional Prog OO Prog
(Lego)
(Lego)
C F
C F
F
C
F CO
O

C O C
F
C
F O
C C
F O
C
F
O
New New
New New New New
New
New New New
New

New New
O
New
New C
New O
New
O
New
Procedural Prog Functional Prog
(Lego)
(tree) C F
C F
F
P1 classA
C
F

P2 P3 classC
C
classB F
F
C C
F
P4 P5 P6
C
F
classD classE

(top down)
Abstraction
• Bird Interface

• Fly Interface Bird{



• Make sound }

• Eat
fun(Bird bird){
• Hunt bird.fly();
}


Good
• DIP
• SRP (***)
• Program. To an Interface (upcast)
• Fun (Max : fit screen, good: 6
• LSP lines)

• Static code analyzer (sonar qube,…)


• Class - wmc ( Max: 12, good
: 5)
• Low Cyclomatic complexity (< 10)

• Boundary Control Entity • Module - (Max: 30 good: 12)

• Soc • Low coupling (**)

• Separate error handling and domain


• ~ uni directional coupling
logic

• Separate domain and boundary • DRY (*)

• Separate domain logic and pure


• OCP (open for add, closed for
fabrication change)
UI layer

Business layer
Bad
• Swiss knife (Util, Helper, Service, …)

• Tight coupling

• * to *

• Static Methods

• Bi directional /cyclic
• Overloading family of
• God Class (Controller, Handler, Orchestrator, Interceptor, ..) class
• Flag (proc)

• Cyclomatic complexity • Down cast


• Bool, null, int for error

• Magic numbers

• Functional Interface

• Type check
no of interface depends on no of flags

flag =:> interface

no of methods => no of place flag is used

no of impl => totla flag values


if

Error Flow control Domain


flag flag Rules
res == true Type == 2 Sal > 5000

# exception 2
Only Logic
Data change
change

# Object per # interface 1


Change. 4 # lamda 3
Coupling
Fun call Allocation deallocation

Examples obj.fun() new CA delete obj

# DI
# Interface typing # Factory
# duck typing @ class factory # gc
Approach @ abstract factory # virtual destructor
# Lamda
@ creator method
@ factory method

# Reflection # Reflection
Extreme
# Adapter
Account Dialog

SA CA SADialog CADialog
<config>
<class>CA</class>
<method>fun</method>
</config>
Tight coupling Interface typing (java) Duck typing (py, js) Lamda (py,js, java)
interface IA{
void f1();
class CA }
{
class CA{ class CA{
void f1(){ class CA implements IA
void f1(){ void f1(){
… {
… …
} void f1(){
} }
} …
} }
}
}

do(CA obj) do(IA obj) do(obj) do(Lamda fun)


{ { { {
obj.f1(); obj.f1(); obj.f1(); fun();
} } } }

CA obj = new CA( )


do(new CA( )) do(new CA( )) do(new CA( ))
do(()-> obj.f1() )
Tight coupling DI Factory
interface IA{
void f1();
interface IA{ }
void f1();
class CA } class CA implements IA{
{ void f1(){
void f1(){ class CA implements IA …
… { }
} void f1(){ }
} … class Factory{
} static IA create(){
} return new CA;
}
}

Set(IA obj){
CA obj = new CA( ); IA obj = Factory.create();
obj.fun();
Obj.fun() obj.fun();
}
void fun(int i)
• Flow control Flag => polymorphism {
if(i <2){
….
• Error flag => exceptions }
else{
….
}
}
Boundary
(technology)

Db UI

Domain/ business API


Email (logic)
Msg
Polymorphism

logic1()
Single Dispatching
? logic2()
# Interface, visitor
logic3()

logic1()
Account Dialog ? logic2() Dual Dispatching
logic3() # Same family : lookup
# Different family : Visitor

logic1()
? logic2() Multi Dispatching
logic3() # Lookup
Single dispatch - virtual fun
class CA{
void fun(){ //1
….
}
}

class CB extends CA{ void do(CA a)


void fun(){ //2 {
…. a.fun(); //1 | 2 | 3
} }
}

class CC extends CB{


void fun(){ //3
….
}
}
Single dispatch - delegate
class CA{ When logic cannot be kept in the
void fun(){ //1 Family
Util u = new Util();
U.fun(this);
}
class Util { }
void fun(CA){ //1
…. class CB extends CA{
} void fun(){ //2 void do(CA a)
void fun(CB){ //2 Util u = new Util(); {
…. U.fun(this); a.fun(); //1 | 2 | 3
} } }
void fun(CC){ //3 }
….
} class CC extends CB{
} void fun(){ //3
Util u = new Util();
U.fun(this);
}
}
Single dispatch - visitor
interface Visitor{
When logic cannot be kept in the
void visit(CA);
Family and also cannot couple to the
void visit(CB);
Delegated class
void visit(CC);
}
class CA{
void accept(Visitor v){ class LogicImp implements Visitor{
v.visit(this); void visit(CA) { } //1
} void visit(CB) { } //2
} void visit(CC) { } //3
}
class CB extends CA{
void accept(Visitor v){
v.visit(this);
}
}
void do(CA a)
class CC extends CB{ {
void accept(Visitor v){ LogicImp obj = new LogicImp();
v.visit(this); a.accept(obj); //1 | 2 | 3
} }
}
Dual dispatch - visitor
interface Visitor{ void do(CA a,CX x){
void visit(CA); a.accept(x); //1 — 9
void visit(CB); }
void visit(CC);
} class CX implements Visitor{
class CA{ void visit(CA) { } //1
void accept(Visitor v){ void visit(CB) { } //2
v.visit(this); void visit(CC) { } //3
} }
} }
class CY implements Visitor{
class CB extends CA{ void visit(CA) { } //4
void accept(Visitor v){ void visit(CB) { } //5
v.visit(this); void visit(CC) { } //6
} }
} }
class CZ implements Visitor{
class CC extends CB{ void visit(CA) { } //7
void accept(Visitor v){ void visit(CB) { } //8
v.visit(this); void visit(CC) { } //9
} }
} }
Dual dispatch

void do(CA a1,CA a2){


Lookup
}
class CA{
}

class CB extends CA{


}

class CC extends CB{


}
Coding Style Proc OO Fun

Performance - - ++

Security - - -

Unit Testability -- ++ +++

Time to develop/
++ -- +
cost

Manage Large Code -- ++ +

Learning Curve ++ -- -

Java, js, py, scala,


Language C, java, js, py Java, js, py
kotlin, Haskel
Conditional

Error == Code Flow == Business Rules <, >, …

Exception Handling Specification

Only Data changes Logic changes


In each Path In Path Rule Engine

Single class,
Object per Path

Coarse grained Functional Interface

Interface / duck Function


Object
Manage
Cyclomatic complexity

Error Flag Flow Flag == Business Rules


Flow

Exception Handling Specification

Only Data changes Logic changes


In Paths In Paths Rule Engine

Single class,
Object per Path

Single dispatch
dual dispatch multi dispatch

Interface / duck
Decision Table

Breaks SRP & 2 objects belonging to 2 objects of


Functional Interface Breaks SRP
coupling different families same family

Function Delegated Visitor Use Lookup


Visitor
Object Interface
Coupling
Method Class Object
Call Instantiation Deallocation

Example obj.fun(); new CA(); delete obj;

Approach1 Interface DI Virtual destructor

Approach 2 Lamda Factory

Approach 3
Principles
• SRP (***) • DRY (*)

• Library max : 30 Avg : 15 classes


• KISS
• Class Max: 12 Avg : 4 public methods
• YAGNI
• Method Max: Fit Screen Avg : 5 lines

• LSP • DIP

• Low Cyclomatic Complexity (< 10) • Low Coupling (**)

• Program to an interface (upcasting)


• Uni directional Coupling
• Prefer Composition over Inheritance
• Boundary Control Entity
• OCP

• SOC • Agregate Root


Anti patterns
• Flag —> interface or duck typing, exceptions. Lamda

• Type Check

• Down casting
• Over loading family
of classes
• Arrow code

• Bool, Null, int for error Handling • Static methods


• Swiss knife/ God Class
• Inheritance (extends)
• Functional Interface (single method interface)<—
lilliputs

• Bi directional coupling

• * to * coupling
Inheritance Ref

Change the parent


No Yes
At runtime

Lazy Load
No Yes
Parent

Multiple Parent No Yes


Seperation of Concerns

• Error handling logic should not be mixed with domain


logic

• Security

• Transaction

• Persistence
SOC

• Boundary (technology) and Domain

• Error logic and Domain

• Separate rules from Logic


Boundary (technology) logic

UI Control
File

Rest Db
Api Domain logic (Entity)
Rest
Message Api
Api
Boundary (technology logic)

Control (flow logic)

Entities (Domain logic)

Aggregates Aggregates

Root, Entities, VO Root, Entities, VO

Aggregates

Root, Entities, VO
API Boundary

Control

Domain

Dao Boundary
API Boundary

Domain

Dao Boundary
Aggregate Root (DDD)
Invoice
-> LineItem
-> Address
Conditions

Error Handling 1 Code flow case == 1 4 Business Rules

Exception Handling Salary > 5000

res== true 2 Only Data changes 3 Logic changes


In Paths In Paths

Class,
Instance per Path
3.1 Coarse Grained
Interface
Functional Interface 3.2

Interface, Function
Implementation per path Object
Manage
Cyclomatic complexity

Error Flag Flow Flag == Business Rules


Flow

Exception Handling Specification

Only Data changes Logic changes


In Paths In Paths Rule Engine

Single class,
Object per Path

Single dispatch
dual dispatch multi dispatch

Interface / duck
Decision Table

2 objects belonging to 2 objects of


Functional Interface Breaks SRP Breaks coupling
different families same family

Function Delegated Visitor Use Lookup


Visitor
Object Interface
Manage
Coupling

Tightly coupled Tightly Coupled


Method call Instantiation

Heterogeneous Homogenous Delegate Control


* to *
Interface Interface Responsibility instantiation

Adapter Mediator Dependancy Injection Class factory

Flags cannot removed Factory contains


(comes from boundary) flag/enum
Static Language Dynamic Language Single Method

Factory with Lookup Factory interface


Interface Typing Duck Typing Function Object
Dependancy among
objects of a family

Manage dependancy Manage instantiation

Builder

1 to * Multiple Cyclic
Multiple Dependancy
Dependancy

Hierarchy of Objects Graph of Objects

Few objects Many Objects

Linked list of objects Collection of objects


(Vertical) (Horizontal)
Manage
Cohesion

Separate Separate Separate Separate Separate Separate Unrelated


Technology Code Cross Cutting Logic Business Rules Error Handling Read/Write Logic Flow and Steps Logic

Exception handling
UI If sal > 5000 If res == false Things which do not
Caching
Database Change together
Log
File Transaction
API Authorization
EMail
Messaging

Layered Design Facade Specification Exception Handling CQS Facade

Boundary Control
Decorator Rule Engine
Entity

Hexagonal Arch AOP

Pipes Filter
Proc OO Fun
(tree) (lego)

C, py, java, C#, JS, Java, C#, C++,


Lang py,js, J8,c#
c++ py, js

if/switch/goto/ Polymorphism/ High order fun/


Constructs
Static methods Exceptions recursion/ closure

Performance - - ++

Security - - -

Learning Curve ++ -- -

Development Time ++ -- +

Unit Test -- + ++

Code Maintainability/
-- ++ +
Support Time
Change behaviour
Change Part of behaviour
Rename behaviour
Enrich behaviour
Add behaviour

CA CA CA CA CA
B1 B1 B1 B1
Client B1
B2 B2 B2 B2 B2

*
CW CA

C1 B1
Client C2 B2

Adapter
Authentication
Autorization
CW CA Audit
B1 Cache
B1
Client B2 Exception Handling
B2
Lazy loading
Simplify network call
Proxy

CW CW CW CW CA
B1 B1 B1 B1
Client B1
B2 B2 B2 B2 B2

Proxy Proxy Proxy Proxy


Decorator
Separation of Concern

• Domain logic and error handling logic

• Domain logic and technology logic


if / switch

Error Handling Alternate Business Rules


Flow Flow Flow

Exception Handling
(Exception per error)
Only Data changes Logic changes
In Paths In Paths

P23 Single class, Interface / duck P22


Object per Path P25 (Implementation Per
P27
Path)

switch(flag)
{
Breaks SRP
Case 1:
Data1 P6
Delegated
Case 2: Interface P21
data2 switch(flag)
Case 3: {
Data3 Case 1:
} Logic1 amount * 0.5;
Case 2:
Logic2 (amount - 5000) * 0.08;
Case 3:
Logic3
}
Method
Instantiation Deallocation
Call

ca.f1(); new CA() delete ca;

Di
Interface # constructor GC
#setter

Factory
# Class Factory
Lamda # Abstract Factory Virtual destructor
# factory Method
# creator Method

Duck typing

Adapter
Code segment Data segment Heap Stack

CX vtbl
CA - 1,
void f(CA a) {} //1 CC
void f(CB b) {} //2 CB - 2,
void f(CC c) {} //3 CC - 3 a
CY vtbl
void f(CA a) {} //4
void f(CB b) {} //5
void f(CC c) {} //6
CA - 4,
CB - 5,
CC - 6
void f(CA a) {} //7
void f(CB b) {} //8
CZ
void f(CC c) {} //9 CZ vtbl x
CA - 7, ? vptr
CB - 8, Runtime x.f(a)
CC - 9 x.vptr.vtbl[0](a)

Compile time
• Boundary and Domain logic is mixed

• Error Handling is mixed with domain logic

• Flow is mixed with steps

• Logic is mixed with rules

• Cyclomatic Complexity


Abstraction

c++, java, C# Py,js Java 8, C#, c++ 11,py, Haskel

Interface typing Duck typing Lamda

Interface Bird
{
fly()
} Explicit Implicit
Implicit

do(Brid bird) do(bird) do(fly)


{ { {
bird.fly(); bird.fly(); fly();
} } }

class Parrot implements Bird class Parrot class Parrot


{ { {
fly() { …. } fly() { …. } flyHigh() { …. }
} } }

p= new Parrot()
do(new Parrot()); do(new Parrot());
do(()=>p.flyHigh());
Composition Inheritance
Lamda
<<stratergy>> <<template method>>

“Change logic interface IX{ class CA


In a Class” void logic2(); class CA {
} { IX ref;
Lamda fun;
class CA void logic2() { … }
class CA { void fun(){
{ IX ref; … logic 1 void fun(){
void fun(){ fun(); … logic 1
… logic 1 void fun(){ … logic 3 logic2();
… logic 2 * … logic 1 } … logic 3
… logic 3 ref.logic2(); } }
} … logic 3 }
} }
} class CB extends CA{
void logic2(){ …. }
}
class CB implements IX{
void logic2(){ …. }
CA o = new CB();
}
o.fun();
CA o = new CA (new CB() );
o.fun();
Composition Lamda
Composition <<Decorator>> <<Currying>>
<<proxy>>
“enrich logic
In a Class” Interface IX{
void fun();
}
class CA implements IX
class wrapper
{
{
void fun(){
class CA CA ref;
… logic
{
}
void fun(){ void fun(){
}
… logic … enrich
} ref.fun(); class wrapper implements IX
} … enrich {
} IX ref;
}
void fun(){
w->CA
… enrich
ref.fun();
… enrich
}
}

w->w->w->w->w->CA
Composition Composition
<<Decorator>> <<COR>>

Interface IX{
void fun();
} Interface IX{
class CA implements IX void fun();
{ }
void fun(){
… logic class CA implements IX
} {
} IX ref;
class wrapper implements IX void fun(){
{ if(cond)
IX ref; … logic //handle
else
void fun(){ ref.fun(); //delegate
… enrich }
ref.fun(); }
… enrich
}
}
CA->CA->CA->CA->CA
w->w->w->w->w->CA
<<Composition>>
Adapter
“change interface
Of Class”

Interface IY{
void fun2();
}
Interface IX{ class Wrapper implements IY
void fun(); {
} CA ref;
class CA implements IX
{ void fun2(){
void fun(){ ref.fun();
… logic }
} }
}

IY y = new Wrapper(new CA);


Y.fun2();
Single dispatch - visitor
interface Visitor{
When logic cannot be kept in the
void visit(CA);
Family and also cannot couple to the
void visit(CB);
Delegated class
void visit(CC);
}
class CA{
void accept(Visitor v){ class LogicImp implements Visitor{
v.visit(this); void visit(CA) { } //1
} void visit(CB) { } //2
} void visit(CC) { } //3
}
class CB extends CA{
void accept(Visitor v){
v.visit(this);
}
}
void do(CA a)
class CC extends CB{ {
void accept(Visitor v){ LogicImp obj = new LogicImp();
v.visit(this); a.accept(obj); //1 | 2 | 3
} }
}
<<Composition>>
State
“change logic
Based on state”
Interface State{
void fun();
}
Class State1 implements State{
class CA void fun(){ ….. }
{ }
data; <—state Class State2 implements State{
void fun(){ void fun(){ ….. }
if(data == x) }
… logic 1 Class State3 implements State{
if(data == y) void fun(){ ….. }
… logic 2 }
if(data == z) class CA {
… logic 3 State ref = new State1();
}
} void fun(){
ref.fun();
changeState();
}
}
<<Factory Method>> <<Class Factory>> <<Abstract Factory>>

class CA class Factory


{ Interface Factory{
{ CA createCA();
void fun(){ CA createCA(){
…. CB createCB();
… logic }
} }
CB createCB(){ class FactoryX
CB createCB(){ implements Factory
…. ….
} {
} CA createCA(){
} ….
} }
<<builder>> CB createCB(){
<<Creator Method>> ….
class Builder }
{
class CA void addCA(){ }
{ ….
void fun(){ } <<Prototype>>
… logic void addCB(){
} …. class CA
} {
Static CB createCB(){ CX getCX(){ CA clone(){
…. …. ….
} } }
} } }
Public 20% <— facade , gateway,
Controller

Internal 80%

You might also like