Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Design Principles For Building Good Software | ...

Design Principles For Building Good Software | Mnats Karakhanyan

As a part of https://swiftcoders.org initiative, SwiftCoders Armenia has an ambitious goal - connect passionate professionals to share their experience, create a great network and make an impact in their communities.
Our speakers are invited from the best IT companies to share their experience and knowledge.

YouTube link
https://youtu.be/yj4CVn0TVoo

Contact Mnats:
LinkedIn: https://www.linkedin.com/in/mnats-karakhanyan
Twitter: https://twitter.com/KarakhanyanMn
Facebook: https://www.facebook.com/mnats.karakhanyan

Join SwiftCoders Armenia
https://swiftcoders.am

Facebook
https://www.facebook.com/swiftcoders
Telegram
https://t.me/SwiftCoders
LinkedIn
https://www.linkedin.com/company/swiftcoders-armenia
Eventbrite
https://www.eventbrite.com/o/swiftcoders-armenia-18287883306
Decks
https://speakerdeck.com/swiftcoders
Slack
https://swiftcodersinvite.herokuapp.com

Avatar for SwiftCoders Armenia

SwiftCoders Armenia

April 03, 2019
Tweet

More Decks by SwiftCoders Armenia

Other Decks in Technology

Transcript

  1. Understanding Problem Design Principles Wrapping Up The problem Design Smells

    Metrics Law of Demeter SOLID Conclusion Bibliography Q&A
  2. • Rigidity • Fragility • Immobility • Viscosity • Needless

    complexity • Needless repetition • Opacity
 Design Smells
  3. • Rigidity • Fragility • Immobility • Viscosity • Needless

    complexity • Needless repetition • Opacity
 Design Smells
  4. • Rigidity • Fragility • Immobility • Viscosity • Needless

    complexity • Needless repetition • Opacity
 Design Smells
  5. • Rigidity • Fragility • Immobility • Viscosity • Needless

    complexity • Needless repetition • Opacity
 Design Smells
  6. • Rigidity • Fragility • Immobility • Viscosity • Needless

    complexity • Needless repetition • Opacity
 Design Smells
  7. • Rigidity • Fragility • Immobility • Viscosity • Needless

    complexity • Needless repetition • Opacity
 Design Smells
  8. • Imposed duplication. Developers feel they have no choice—the environment

    seems to require duplication. • Inadvertent duplication. Developers don't realize that they are duplicating information. • Impatient duplication. Developers get lazy and duplicate because it seems easier. • Interdeveloper duplication. Multiple people on a team (or on different teams) duplicate a piece of information.
  9. • Rigidity • Fragility • Immobility • Viscosity • Needless

    complexity • Needless repetition • Opacity
 Design Smells
  10. “Vertical and horizontal lines are positioned in layers or planes

    that do not intersect, thereby allowing each element to exist independently and unobstructed by other elements” Piet Mondrian
  11. Violation of the law class Employee { var address: Address

    } class BasicExample { func streetName(for employee: Employee)-> String { return employee.address.streetName } }
  12. Respect the law class Employee { private var address: Address

    = Address() var streetName: String { return address.streetName } } class BasicExample { func streetName(for employee: Employee) ->String { return employee.streetName } }
  13. The more objects you talk to, more the risk of

    getting broken when any one of the object changes.
  14. The more objects you talk to, more the risk of

    getting broken when any one of the object changes. Restrict class interaction in order to minimize coupling among classes.
  15. • Only invoke methods that belong to ‣ The object

    itself ‣ Objects passed in as parameter to method ‣ An object the method created or instantiates ‣ Any components of the object • As a guidance-rule, more than two “dots” 
 means the Law of Demeter is being violated.
  16. SOLID S: Single Responsibility Principle(SRP) O: Open-Closed Principle(OCP) L: Liskov

    Substitution Principle(LSP) I: Interface Segregation Principle(ISP) D: Dependency Inversion Principle(DIP)
  17. Violation of SRP class Handler { func handle() { let

    data = requestDataToAPI() let array = parse(data: data) saveToDB(array: array) } private func requestDataToAPI() -> Data { // send API request and wait the response } private func parse(data: Data) -> [String] { // parse the data and create the array } private func saveToDB(array: [String]) { // save the array in a database } }
  18. Solution class APIHandler { func requestDataToAPI() -> Data { //

    send API request } } class ParseHandler { func parse(data: Data) -> [String] { // parse the data } } class DBHandler { func saveToDB(array: [String]) { // save the array in a database }
  19. Solution class Handler { let apiHandler: APIHandler let parseHandler: ParseHandler

    let dbHandler: DBHandler func handle() { let data = apiHandler.requestDataToAPI() let array = parseHandler.parse(data: data) dbHandler.saveToDB(array: array) } }
  20. Violation of OCP class AnaliticServise { func track(_ event: String,

    parameters: [String: Any]?) { // tracks an event in Facebook } }
  21. Solution class GoogleAtalitics: AnaliticTracker { func track(_ event: String, parameters:

    [String: Any]?) { // tracks an event in google GoogleAtalitics } } class FacebookAtalitics: AnaliticTracker { func track(_ event: String, parameters: [String: Any]?) { // tracks an event in Facebook } }
  22. Solution class AnaliticServise: AnaliticTracker { private let analiticTrackers: [AnaliticTracker] init(analiticTrackers:

    [AnaliticTracker]) { self.analiticTrackers = analiticTrackers } func track(_ event: String, parameters: [String: Any]?) { for tracker in analiticTrackers { tracker.track(event, parameters: parameters) } } }
  23. The Wrong Abstraction Duplication is far cheaper than the wrong

    abstraction Composition over inheritance
  24. LSP Functions that use pointers or references to base classes

    must be able to use objects of derived classes without knowing it
  25. Violation of LSP class Rectangle { var width: Float =

    0 var hight: Float = 0 var area: Float { return width * hight } } class Square: Rectangle { override var width: Float { didSet { hight = width } } } let rectangle = Rectangle() rectangle.hight = 4 rectangle.width = 3 print(rectangle.area) // 12 let square = Square() square.hight = 4 square.width = 3 print(square.area) // 9
  26. Solution class Rectangle: Polygon { private let width: Float private

    let hight: Float init(width: Float, hight: Float) { self.width = width self.hight = hight } var area: Float { return width * hight } }
  27. Solution class Rectangle: Polygon { private let width: Float private

    let hight: Float init(width: Float, hight: Float) { self.width = width self.hight = hight } var area: Float { return width * hight } } class Square: Polygon { private let side: Float init(side: Float) { self.side = side } var area: Float { return pow(side, 2) } }
  28. Solution class Rectangle: Polygon { private let width: Float private

    let hight: Float init(width: Float, hight: Float) { self.width = width self.hight = hight } var area: Float { return width * hight } } class Square: Polygon { private let side: Float init(side: Float) { self.side = side } var area: Float { return pow(side, 2) } } let rectangle = Rectangle(width: 3, hight: 4) print(rectangle.area) // 12 let square = Square(side: 3) print(square.area) // 9
  29. Violation of ISP class StandardWorker: Worker { func work() {

    print("Standard Worker is working") } func eat() { print(“Standard Worker is eating") } } class SuperWorker: Worker { func work() { print("Super Worker is working") } func eat() { print("Super Worker is eating") } }
  30. Violation of ISP class Robot: Worker { func work() {

    print("Robot working... efficiently") } func eat() { assert(false, “Don't force me to eat, or i will crash") } }
  31. class StandardWorker: Workable, Feedable { func work() { print("Standard Worker

    is working") } func eat() { print(“Standard Worker is eating") } }
  32. class StandardWorker: Workable, Feedable { func work() { print("Standard Worker

    is working") } func eat() { print(“Standard Worker is eating") } } class SuperWorker: Workable, Feedable { func work() { print("Super Worker is working") } func eat() { print("Super Worker is eating") } }
  33. class StandardWorker: Workable, Feedable { func work() { print("Standard Worker

    is working") } func eat() { print(“Standard Worker is eating") } } class SuperWorker: Workable, Feedable { func work() { print("Super Worker is working") } func eat() { print("Super Worker is eating") } } class Robot: Workable { func work() { print("Robot working... efficiently") } }
  34. DIP High-level modules should not depend on low-level modules. Both

    should depend on abstractions. Abstractions should not depend on details. Details should depend on abstractions
  35. Violation of DIP class Handler { let fm = FilesystemManager()

    func handle(string: String) { fm.save(string: string) } } class FilesystemManager { func save(string: String) { // Save the string in this file } }
  36. Solution class FilesystemManager: Storage { func save(string: String) { //

    Save the string in the file } } class DatabaseManager: Storage { func save(string: String) { // Save the string in the data base } }
  37. Solution class Handler { let storage: Storage init(storage: Storage) {

    self.storage = storage } func handle(string: String) { storage.save(string: string) } }
  38. Clean Code: A Handbook of Agile Software Craftsmanship 
 by

    Robert C. Martin The Pragmatic Programmer: From Journeyman to Master by Andy Hunt Agile Software Development, Principles, Patterns, and Practices by Robert C. Martin Head First Design Patterns by Eric Freeman