Presented by Raman But-Husaim
Lead Software Engineer at
12+ years of programming
7+ years in production
Master's Degree in Software Engineering
Microsoft Certified Specialist
Raman But-Husaim
Software application architecture is the process of defining a structured solution that meets all of the technical and operational requirements, while optimizing common quality attributes such as performance, security, and manageability.
by some guy at Microsoft
Monolith
Microservices
Source: http://www.myrecipes.com/recipe/rainbow-layer-cake
Tier refers to physical distribution patterns
Layers are concerned with the logical division of components and functionality
Layer interaction rules
Layer interfaces
Source: http://mixedsign.com/tag/concept-art-world/page/5/
Source: Telegram Great Minds sticker pack
A class should have only one reason to change.
Gather together the things that change for the same reasons. Separate those things that change for different reasons.
by Robert C. Martin
OR
Source: https://vikingmarine.ie/products/victorinox-skipper-mutli-tool
public sealed class Page
{
private readonly Book book;
public Page(Book book)
{
this.book = book;
}
public string Content => "something";
public override string ToString()
{
return Content;
}
}public sealed class Book
{
public string Title => "Hyperion";
public string Author => "Dan Simmons";
public Page GetCurrentPage()
{
return new Page(this);
}
public void PrintCurrentPage()
{
Console.WriteLine(GetCurrentPage());
}
}Source: Telegram Great Minds sticker pack
public sealed class Book
{
public string Title => "Hyperion";
public string Author => "Dan Simmons";
public Page GetCurrentPage()
{
return new Page(this);
}
}
public interface IPagePrinter
{
void PrintPage(Page page);
}Source: Telegram Great Minds sticker pack
public class TextPagePrinter : IPagePrinter
{
public void PrintPage(Page page)
{
Console.WriteLine(page.ToString());
}
}
public class HtmlPagePrinter : IPagePrinter
{
public void PrintPage(Page page)
{
var content = $"<div>" +
$"{page.Content}" +
$"</div>";
Console.WriteLine(content);
}
}Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.
by Bertrand Mayer
public abstract class Shape
{
}
public class Rectangle : Shape
{
public double Width { get; set; }
public double Height { get; set; }
}
public class Circle : Shape
{
public double Radius { get; set; }
}public class AreaCalculator
{
public double CalculateArea(Shape[] shapes)
{
double area = 0;
foreach (var shape in shapes)
{
if (shape is Rectangle)
{
Rectangle rectangle = (Rectangle) shape;
area += rectangle.Width * rectangle.Height;
}
else
{
Circle circle = (Circle) shape;
area += circle.Radius
* circle.Radius
* Math.PI;
}
}
return area;
}
}Source: Telegram Great Minds sticker pack
public abstract class Shape
{
public abstract double CalculateArea();
}
public class Rectangle : Shape
{
public double Width { get; set; }
public double Height { get; set; }
public override double CalculateArea()
{
return Width * Height;
}
}
public class Circle : Shape
{
public double Radius { get; set; }
public override double CalculateArea()
{
return Radius * Radius * Math.PI;
}
}public class AreaCalculator
{
public double CalculateArea(Shape[] shapes)
{
double area = 0;
foreach (var shape in shapes)
{
area += shape.CalculateArea();
}
return area;
}
}Source: Telegram Great Minds sticker pack
Derived class objects must be substitutable for the base class objects. That means objects of the derived class must behave in a manner consistent with the promises made in the base class' contract.
from http://wiki.c2.com/?LiskovSubstitutionPrinciple
Source: Telegram Great Minds sticker pack
public class Rectangle
{
public virtual double Width { get; set; }
public virtual double Height { get; set; }
}
public class Square : Rectangle
{
private double width;
private double height;
public override double Width
{
get => width;
set
{
width = value;
height = value;
}
}
... public override double Height
{
get => height;
set
{
width = value;
height = value;
}
}
}
public sealed class Client
{
public void VerifyArea(Rectangle rect)
{
rect.Width = 20;
rect.Height = 4;
// expected area - 80
// actual - 16
}
}Clients should not be forced to depend on methods that they do not use.
by Robert C. Martin
public interface ILogger
{
void Log(string message);
void OpenConnection();
void CloseConnection();
}
public class DBLogger : ILog
{
public void Log(string message)
{
...
}
public void OpenConnection()
{
...
}
public void CloseConnection()
{
...
}
}public class FileLogger : ILog
{
public void Log(string message)
{
...
}
}Source: Telegram Great Minds sticker pack
public interface ILogger
{
void Log(string message);
}
public interface IDBLog: ILog
{
void OpenConnection();
void CloseConnection();
}
public interface IFileLog: ILog
{
long GetFileSize();
}
Source: Telegram Great Minds sticker pack
High-level modules should not depend on low-level modules. Both should depend on abstractions.
Abstractions should not depend upon details. Details should depend upon abstractions.
by Robert C. Martin
Example: С. Тепляков "Паттерны проектирования на платформе .NET"
public interface IReportFormatter
{
string FormatReport(Report report);
}
public class Reporter
{
private readonly IReportFormatter formatter;
public Reporter(IReportFormatter formatter)
{
this.formatter = formatter;
}
public void SendReport(Report report)
{
var formattedReport = this.formatter.FormatReport(report);
SendFormattedReport(formattedReport);
}
private void SendFormattedReport(string formattedReport)
{}
}
Example: С. Тепляков "Паттерны проектирования на платформе .NET"
class XlsFormatter : IReportFormatter
{
public string FormatReport(Report report)
{
}
}
class Application
{
public void Run()
{
var reporter = new Reporter(new XlsFormatter());
reporter.SendReport(GenerateReport());
}
}
Example: С. Тепляков "Паттерны проектирования на платформе .NET"
Source: http://brandonclapp.com/what-is-dependency-injection-and-why-is-it-useful/
Dependency Injection is a set of software design principles and patterns
that enable us to develop loosely coupled code.
by Mark Seemann
When you go and get things out of the refrigerator for yourself, you can cause problems. You might leave the door open, you might get something Mommy or Daddy doesn’t want you to have. You might even be looking for something we don’t even have or which has expired.
What you should be doing is stating a need, “I need something to drink with lunch,” and then we will make sure you have something when you sit down to eat.
by John Munch
Benefits of DI
Stable Dependencies - challenge DI
Volatile Dependencies - use DI
public interface IWeapon
{
void Hit(string target);
}
public sealed class Samurai
{
private readonly IWeapon weapon;
public Samurai(IWeapon weapon)
{
this.weapon = weapon;
}
public void Attack(string target)
{
this.weapon.Hit(target);
}
}Source: https://softwareengineering.stackexchange.com/a/177661
Constructor should be your default choice for DI. It addresses the most
common scenario where a class requires one or more dependencies, and no reasonable
local defaults are available.
public interface IDependency
{
}
internal class DefaultDependency : IDependency
{ }
public class CustomService
{
public CustomService()
{
Dependency = new DefaultDependency();
}
public IDependency Dependency { get; set; }
}
Source: http://sergeyteplyakov.blogspot.de/2013/01/di-property-injection.html
Should only be used when the class you’re developing has a good
local default and you still want to enable callers to provide different implementations
of the class’s dependency.
public string DoStuff(SomeValue value, ISomeContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
return context.Name;
}Source: http://sergeyteplyakov.blogspot.de/2013/02/di-method-injection.html
Best used when the dependency can vary with each method call.
This can be the case when the dependency itself represents a value.
Source: Telegram Great Minds sticker pack
Source: Telegram Great Minds sticker pack
Source: https://www.amazon.com/Piece-Sleeping-Bubble-Cartoon-Sticker/dp/9099000626
Source: Telegram Great Minds sticker pack