架構師訓練營 week2 總結

用户头像
ilake
关注
发布于: 2020 年 09 月 27 日

1. 从编程历史看面向对象编程的本质与未来

Goal of programing

  • use a computer to solve problems of the real world

  • Process of programing:

  • build the relationship between “computer’s model” and questions of the real world.

  • Programing is an “abstract” mechanism, the question is “abstract whom"

What is OOP?

  • Everything is an object

  • Objects communicate only by sending each other messages

  • Every object is an instance of a class.

  • Classes are used to define the set of messages an instance of that class responds to, as well as the variables contained in every instance of that class

What is Object?

  • state: each object can have its own data

  • behavior: each object can do something 

  • Identity: every object is different (uniq address)

3 factors of OOP

  • Encapsulation

  • Hide implementation detail

  • Inheritance

  • IS-A 

  • Polymorphism

  • the sender of a stimulus does not need to know the receiving instance’s class. The receiving instance can belogin to an arbitrary class





The goals of OOP

high cohesion and low coupling

  • Extend: easy to add a new feature

  • Strong

  • Porting: can run in different environments

  • Simple: easy to understand and maintain

Frameworks

  • A tool that allows to develop software and create systems.

  • An Implementation of a real architecture design

  • Provide some design patterns, let developers design a good program easily

Frameworks VS Library

  • a framework uses programming code

  • Programing code uses a library

  • The architect uses a framework to make sure architecture landing

  • The architect uses the library to improve the effectiveness



2. 糟糕的代码有哪些特点?

Bad smell code

  • Rigidity: not easy to update 

  • Rigid code is resistance to change, change it, and you have to change something else

  • Fragility: update A but break B

  • Fragile code breaks due to external changes or untested uses of the system

  • Immobility: hard to reuse

  • Viscosity: changes or additions are easier to implement by doing the wrong thing

  • Opacity

  • Needless Complexity

  • Needless Repetition



One bad case

  • Copy from keyboard and write to printer



it should be



Abstract “Copy” 

  1. Copy from where => Reader

  2. Copy to where => Writer



One use case

  • 我們按下數字按鈕,屏幕上顯示號碼,揚聲器發出按鍵音

  • 我們按下 send 按鈕,系統接通無線網路,同時銀幕顯示正在撥號



  1. 所有的名詞都可能是潛在的對象,誰是使用系統的主要功能者

  2. 可以進行交互,上面有行為的東西才能成為對象



先找出名詞:

  1. 數字按鈕

  2. 屏幕

  3. 號碼 => 不能交互、沒有行為

  4. 揚聲器

  5. 按鍵音 => 不能交互、沒有行為

  6. Send 按鈕

  7. 系統 => 代表整個系統,所以也不用算在物件裡面

  8. 無線網路 => 不能交互、沒有行為





What is the problem:

  • Rigidity

  • If I want to add one more “Button" type, I need to update the button class

  • If I update Dialer, it might affect “Button" 

  • Fragility

  • Switch, if/else is fragile

  • Immobility

  • Buttons of coded lock only need digit buttons, but the current design let them have to have “send” button 



3. 开闭原则介绍及代码分析

OCP: Open/Closed Principle

  • Open for extension

  • Extend Module, Class, Method

  • Closed for modification

  • Not update current Module, Class, Method



  1. What we need to do it let modification can be more “concentrated", “fewer”, “in high level”. Let the most complicated logic part to meet OCP

  2. We should always think about “Extension”, “Abstraction”, “Encapsulation"

  3. Encapsulate changeable part and provide abstract non-changeable interface



sample code

class Button
def initialize
@listeners = []
end
def add_listener(listener)
raise "listener is null" unless listener
@listeners << listener
end
def press
@listeners.each do |listener|
listener.button_pressed
end
end
end



class DigitButtonListener << ButtonListener
def initialize(dialer, digit)
@digit = digit
@dialer = dialer
end
def button_pressed
@dialer.enter_digit(@digit)
end
end



class SendButtonListener << ButtonListener
def initialize(dialer)
@dialer = dialer
end
def button_pressed
@dialer.dial
end
end



class Phone
attr_reader :digit_buttons, :send_button
def initialize
@dialer = Dialer.new
@digit_buttons = init_digit_buttons
@send_button = init_send_button
end
def init_digit_buttons
digit_buttons = []
10.times do |i|
button = Button.new
button_listener = DigitButtonListener.new(i)
button.add_listener(button_listener)
digit_buttons << button
end
digit_buttons
end
def init_send_button
button = Button.new
button_listener = SendButtonListener.new(@dialer)
button.add_listener(button_listener)
end
end



phone = Phone.new
phone.digit_buttons[9].press
phone.send_button.press



4. 依赖倒置原则介绍及代码案例分析

DIP: Dependency Inversion Principle

  • 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.



What does “Inversion” do?

  • Dependence of modules

  • Order and responsibility of development



Hierarchical software design

  • High level module decide low level module







當我們設計框架時,要時時記住依賴倒置原則。

  1. 找出目前物件的本質,設計出接口

  • Button 的本質是什麼

  • 檢測用戶的案件指令,並傳遞給目標對象

  • 用什麼機制檢測 => 不重要 => 由不同的低層模塊實現、擴展

  • 目標對象是什麼 => 不重要 => 由不同的低層模塊實現、擴展

  1. 它幫助我們專注於高層的設計,並且提醒我們高層不應該依賴於低層,永遠要設計抽象化接口

Ex:

Tomcat (high level) and Java Web (low level)

  • Both rely on “Servlet specification"

  • “Servlet specification” does not rely on the detail of Tomcat or Java Web 



5. 里氏替换原则

子類可以替換父類,那繼承就是合理的

子類完美繼承父類的設計初衷,並做了增強



Design by contract



Child class design should follow the father's class’s contract. Father defines the behavior of the function, then the child can update the detailed logic, but the child can’t update the original behavior.

  • Input, output, error handling.

  • Child <-> Father => Implementation <-> Interface



設計和界定一個類,應該以其行為作為區分

When you design and define classes, you should use “behavior” to define different classes



How to fix the LSP issue?

  • Put the same behaviors to a base class

  • Use assembly instead of inherited

How to validate LSP?

  • Check from the context

6 单一职责接口隔离

SRP: Single Responsibility Principle

  • There should never be more than one reason for a class to change.

Anti patten

fix it

How to separate classes? 

  • clarify the responsibility 



出現這些情況,容易不符合 SRP

  1. 類中的代碼行數、函數或者屬性過多;

  2. 類依賴的其他類過多,或者依賴類的其他類過多;

  3. 私有方法過多;

  4. 比較難給類起一個合適的名字;

  5. 類中大量的方法都是集中操作類中的某幾個屬性。



ISP: Interface Segregation Principlew

  • Clients should not be forced to depend upon interfaces that they do not use

  • 接口

  • 一組 API 接口集合

  • 在設計為服務或者類庫接口的時候,如果部分接口只被部分調用者使用,那我們就需要將這部分接口隔離出來,單獨給對應的調用者使用,而不是強迫其他調用者也依賴這部份不會被用到的接口

  • 單個 API 的接口或函數

  • 函數的設計要功能單一,不要將多個不同的功能邏輯在一個函數中實現

  • OOP 中的接口概念

  • 接手的設計要盡量單一,不要讓接口的實現類和調用者,依賴不需要的接口函數

ISP and SRP

  • Related cohesion

  • SRP => how to design a class => There should never be more than one reason for a class to change.

  • ISP => how to design an interface => from clients' view, they should not be forced to depend upon interfaces that they do not use



It is very difficult to fully meet SRP, but we still can use ISP to separate to different interfaces and then limit the effect scope when changing 



用户头像

ilake

关注

还未添加个人签名 2019.04.15 加入

还未添加个人简介

评论

发布
暂无评论
架構師訓練營 week2 總結