Hello

Open Closed Principle

> whoami

michele.damico@gmail.com

https://github.com/la10736

https://www.linkedin.com/in/damico/

@PhenoCoder

Open/Closed Principle

  • S ingle Responsibility Principle (SRP)
  • O pen/Closed Principle (OCP)
  • L iskov substitution Principle (LSP)
  • I nterface Segregation Principle (ISP)
  • D ependency Inversion Principle (DIP)

Open/Closed Principle

Si... Si... Ma in soldoni?

Un modulo rispetta l' OCP se:

Open - Closed

  • Open: possiamo aggiungere funzionalita'

  • Closed: Non dobbiamo modificarlo

Esempio: Sort

fn main() {

    let mut v = vec![3,5,1,2];
    
    v.sort();

    println!("{:?}", v);
    
    v.sort_by(|a, b| a.cmp(b).reverse());
    
    println!("{:?}", v);
}
   Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 1.29s
     Running `target/debug/playground`

[1, 2, 3, 5]
[5, 3, 2, 1]

Come impariamo a Applicarlo?

OCP Kata

OCP Kata Rules

0. Scrivere il primo test che fallisce e poi costruire una factory che ritorna un oggetto o un aggregato che fanno passare il test

  1. Scrivere il prossimo test che fallisce
  2. Rifattorizzare il codice per ospitare la nuova funzionalita'
  3. Modificare la factory per far passare il test
  4. Tornare a 1

OCP Kata Rules (cont)

  • Puo' solo costruire oggetti e agganciarli
  • NON sono ammessi costrutti condizionali

Factory

Durante il refactoring

  • Non e' ammesso che accidentalmente passi il nuovo test

FizzBuzz

  1. I multipli di 3 stampano Fizz
  2. I multipli di 5 stampano Buzz
  3. I multipli di 3 e 5 stampano FizzBuzz
  4. Altrimenti stampano il numero

Per ogni numero da 1 a 100...

fn main() {
    for i in 1..101 {
        println!("{}",
            if i % 15 == 0 {
                "FizzBuzz".to_string()
            } else if i % 3 == 0 {
                "Fizz".to_string()
            } else if i % 5 == 0 {
                "Buzz".to_string()
            } else { 
                format!{"{}", i}
            }
        )
    }
}

FizzBuzz... OCP

trait Apply {
    fn apply(&self, i: i32) -> String;
}

struct DefaultApply;

impl Apply for DefaultApply {
    fn apply(&self, _i: i32) -> String {
        format!("{}", "Maybe you should replace DefaultApply \
                       by something else")
    }
}

pub fn fizzbuzz() -> impl Apply {
    DefaultApply
}
    #[test]
    fn otherwise_should_return_the_number() {
        let fb = fizzbuzz();

        assert_eq!("2", &fb.apply(2));
        assert_eq!("8", &fb.apply(8));
    }

//    #[test]
//    //#[should_panic]
//    fn should_return_fizz_for_multiple_of_3() {
//        let fb = fizzbuzz();
//
//        assert_eq!("Fizz", &fb.apply(3));
//        assert_eq!("Fizz", &fb.apply(36));
//    }

Alcuni Costrutti

trait ATrait {
    fn method(&self, i: i32);
}

struct S;
impl ATrait for S {
    fn method(&self, i: i32) {
        // .... impl
    }
}

impl<A: ATrait, B: ATrait> ATrait for (A, B) {
    fn method(&self, i: i32) {
        // .... impl
    }
}
trait ATrait {
    // Some methods
}

trait BTrait {
    // Some methods
}

impl <A: ATrait> BTrait for A {
    // Implementazione dei metodi di BTrait 
    // usando il fatto che A implementa ATrait 
}

Composite

pub trait Action {
    fn do_action(&self);
}
pub struct ActionComposite {
    actions: Vec<Box<A>>
}

impl ActionComposite {
    pub fn new(actions: Vec<Box<Action>>) -> Self {
        ActionComposite { actions }
    }
}

impl A for ActionComposite {
    fn do_action(&self) {
        for a in &self.actions {
            a.some()
        }
    }
}
pub trait Action {
    fn do_action(&self);
}
impl<A: Action, B: Action> Action for (A, B) {
    fn do_action(&self) {
        self.0.do_action();
        self.1.do_action();
    }
}

pub trait Compose: Sized {
    fn compose<A>(self, other: A) -> (Self, A) {
        (self, other)
    }
}

impl<A> Compose for A {}

Si Parte!

> git clone https://github.com/la10736/ocp_fizzbuzz

Un Possibile Risultato

> git checkout completed_no_builder

Hello Open Closed Principle

By Michele D'Amico

Hello Open Closed Principle

Cosa e' Open Closed Principle e come possiamo imparare a implementarlo.

  • 266