Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

Dobry kod OO. S.O.L.I.D 5 podstawowych wzorców dotyczących programowania zorientowanego obiektowo zdefiniowane przez Roberta C.Martina (szefu Object mentor.

Podobne prezentacje


Prezentacja na temat: "Dobry kod OO. S.O.L.I.D 5 podstawowych wzorców dotyczących programowania zorientowanego obiektowo zdefiniowane przez Roberta C.Martina (szefu Object mentor."— Zapis prezentacji:

1 Dobry kod OO

2 S.O.L.I.D 5 podstawowych wzorców dotyczących programowania zorientowanego obiektowo zdefiniowane przez Roberta C.Martina (szefu Object mentor Inc., międzynarodowy konsultant do spraw rozwoju oprogramowania, przewodniczył grupie odpowiedzialnej za stworzenie „Agile software development”, twórca książek takich jak: „Designing Object-Oriented C++ Applications using the Booch Method”, „Agile Software Development: Principles, Patterns and Practices”, „Clean Code”)

3 SRP – Single Resposibility Principle Jeden powód do zmian! Pozwala na separację poszczególnych modułów Jest jedną z najprostszych zasad ale jedną z najtrudniejszych do poprawnego zastosowania Szukanie i separacja odpowiedzialności jest tak naprawdę wszystkim o co chodzi w tworzeniu oprogramowania

4 Aplikacja do geometri analitycznej Aplikacja graficzna Aplikacja graficzna GUI Rectangle + draw() + area() : double Rectangle + draw() + area() : double

5 Aplikacja do geometri analitycznej Aplikacja graficzna Aplikacja graficzna GUI Rectangle + draw() Rectangle + draw() Geometric Rectangle + area() : double Geometric Rectangle + area() : double

6 interface Modem { public void dial(String pno); public void hangup(); public void send(char c); public char recv(); }

7 > Data Channel + send(:char) + recv() : char > Data Channel + send(:char) + recv() : char > Connection + dial(pno : String) + hangup() > Connection + dial(pno : String) + hangup() Modem implementation Modem implementation

8 OCP – Open-Closed Principle Elementy oprogramowania (klasy, moduły, funkcje itd.) powinny być otwarte na rozszerzanie, ale zamknięte na modyfikację. Kiedy pojedyncza zmiana w kodzie wywołuję łańcuch innych zmian w modułach zależnych oznacza to „zły” projekt Powinno się projektować moduły, które nigdy się nie zmieniają

9 Client Server Zamknięty klient

10 Client Abstract Server Abstract Server Otwarty klient Server

11 Aplikacja rysująca kółka i kwadraty Aplikacja posiada listę kółek i kwadratów Kółka i kwadraty muszą być rysowanę zgodnie z kolejnością na liście

12 enum ShapeType {circle, square}; struct Shape { ShapeType itsType; }; struct Circle { ShapeType itsType; double itsRadius; Point itsCenter; }; struct Square { ShapeType itsType; double itsSide; Point itsTopLeft; }; void DrawSquare(struct Square*) void DrawCircle(struct Circle*);

13 typedef struct Shape *ShapePointer; void DrawAllShapes(ShapePointer list[], int n) { int i; for (i = 0; i < n; i++) { struct Shape* s = list[i]; switch (s->itsType) { case square: DrawSquare((struct Square*)s); break; case circle: DrawCircle((struct Circle*)s); break; }

14 class Shape { public: virtual void Draw() const = 0; }; class Square : public Shape { public: virtual void Draw() const; }; class Circle : public Shape { public: virtual void Draw() const; }; void DrawAllShapes(Set & list) { for (Iterator it(list); it; it++) (*it)->Draw(); }

15 class Shape { public: virtual void Draw() const = 0; virtual bool Precedes(const Shape&) const = 0; bool operator<(const Shape& s) {return Precedes(s);} }; void DrawAllShapes(Set & list) { OrderedSet orderedList = list; orderedList.Sort(); for (Iterator it(orderedList); it; it++) (*it)->Draw(); } bool Circle::Precedes(const Shape& s) const { if (dynamic_cast (s)) return true; else return false; }

16 class Shape { public: virtual void Draw() const = 0; virtual bool Precedes(const Shape&) const; bool operator<(const Shape& s) const {return Precedes(s);} private: static char* typeOrderTable[]; }; char* Shape::typeOrderTable[] = { “Circle”, “Square”, 0 };

17 bool Shape::Precedes(const Shape& s) const { const char* thisType = typeid(*this).name(); const char* argType = typeid(s).name(); bool done = false; int thisOrd = -1; int argOrd = -1; for (int i = 0; !done; i++) { const char* tableEntry = typeOrderTable[i]; if (tableEntry != 0) { if (strcmp(tableEntry, thisType) == 0) thisOrd = i; if (strcmp(tableEntry, argType) == 0) argOrd = i; if (argOrd > 0 && thisOrd > 0) done = true; } else done = true; } return thisOrd < argOrd; }

18 OCP wiąże się z kilkoma innymi utartymi zasadami Wszystkie zmienne klasy powinny być prywatne

19 Co gdy dane pole nigdy się nie zmieni? Czy istnieje powód, żeby czynić je polem prywatnym? class Device { public: bool status;//status ostatniej operacji na //urządzeniu };

20 class Time { public: int hours, minutes, seconds; Time& operator-=(int seconds); Time& operator+=(int seconds); bool operator< (const Time&); bool operator> (const Time&); bool operator==(const Time&); bool operator!=(const Time&); };

21 Żadnych zmiennych globalnych – Nigdy Żaden moduł, który zależy od zmiennej globalnej nie może zostać zamknięty względem innego modułu, jeśli ten inny moduł korzysta z tej zmiennej.

22 LSP – Liskov Substitution Principle Definicja Barbary Liskov: Jeśli dla każdego obiektu o1 typu S istnieje obiekt o2 typu T, taki że dla każdego programu P zdefiniowanego w kontekście typu T, zachowanie programu P pozostaje niezmienione kiedy o1 jest podmieniane obiektem o2, to prawdziwe jest, że typ S jest podtypem typu T. Funkcje, które używają wskaźników lub referencji do klas bazowych muszą być w stanie używać obiektów klas dziedziczących po klasach bazowych bez dokładnej znajomości tych obiektów

23 LSP Jeśli twój kod oczekuje jakiejś klasy, to zamiast niej powinieneś móc podstawić dowolną klasę z niej dziedziczącą bez zmieniania żadnych oczekiwanych zachowań. Jeśli przeciążasz metodę, napisz ją tak, by użyta polimorficznie działała poprawnie

24 Klasyczny problem kwadratu i prostokąta class Rectangle { protected int m_Width; protected int m_Height; public void SetWidth(int width) { m_Width = width; } public void SetHeight(int height) { m_Height = height; } public int GetWidth() { return m_Width; } public int GetHeight() { return m_Height; } public int GetArea() { return m_Width * m_Height; } }

25 class Square: Rectangle { public void SetWidth(int width) { m_Width = width; m_Height = width; } public void SetHeight(int height) { m_Width = height; m_Height = height; } Rectangle r = new Square(); r.SetWidth(5); r.SetHeight(10); int area = r.GetArea();

26 public class User { protected String login; protected String password; protected List modules; public void addAccessToModule(Module module) { modules.add(module); } public boolean canAccess(Module module) { return modules.contains(module); }

27 public class Admin extends User { private List administeredModules; public boolean canAccess(Module module) { return administeredModules.contains(module); } public void subscribeToEvents(User user, Module module) { if (! user.canAccess(module)) { user.addAccessToModule(module); } module.sendEventsTo(user); }

28 LSP Design by Contract. Klasy definiują warunki wejściowe i wyjściowe metod Odpowiednia dokumentacja.

29 ISP – Interface Segregation Principle Klienci nie powinni być zmuszani do bycia zależnymi od metod, których nie używają. Likwiduje „grube” interfejsy

30 interface IWorker { void Work(); void Eat(); } class Worker: IWorker { public void Work() { } public void Eat() { } class Robot: IWorker { public void Work() { } public void Eat() { throw new NotImplementedException(); }

31 interface IWorkable { public void Work(); } interface IFeedable { public void Eat(); } class Worker: IWorkable, IFeedable { public void Work() { } public void Eat() { } class Robot: IWorkable { public void Work() { }


Pobierz ppt "Dobry kod OO. S.O.L.I.D 5 podstawowych wzorców dotyczących programowania zorientowanego obiektowo zdefiniowane przez Roberta C.Martina (szefu Object mentor."

Podobne prezentacje


Reklamy Google