az objektum-orientált tervezési alapelvek kritikai vizsgálata
Post on 07-Feb-2016
35 Views
Preview:
DESCRIPTION
TRANSCRIPT
AZ OBJEKTUM-ORIENTÁLT TERVEZÉSI ALAPELVEK KRITIKAI VIZSGÁLATA
Kusper Gábor, EKF, MatInf IntézetMárien Szabolcs, Wit-Sys ZRt.
Tartalom Tervezési alapelvek:
GOF1, GOF2, SRP, OCP Egy új elv: DLP – Decision Lifting
Principle Néhány összefüggés a régi és az új elvek
közt: OCP ~ DLP GOF2 ~ DLP
Összefoglaló
GOF könyv
GOF1 „Program to an interface, not an
implementation!” „Programozz felületre implementáció
helyett!”
GOF1 megszegése 1. import java.util.*; public class MyHashSet extends HashSet{ private int addCount = 0; public boolean add(Object o){ addCount++; return super.add(o); } public boolean addAll(Collection c){ addCount += c.size(); return super.addAll(c); } public int getAddCount(){ return addCount; } }
GOF1 megszegése 2. import java.util.*; public class Main { public static void main(String[] args){ HashSet s = new MyHashSet(); String[] abc = {"a","b","c"}; s.addAll(Arrays.asList(abc)); System.out.println(s.getAddCount()); } }
GOF1 következményei Kerülni kell az öröklést, vagy legalább Kerülni kell a super (C#-ban base) hívásokat.
A kliens csak a szolgáltató felületét ismerje.azaz A szolgáltatás egy absztrakt osztály / interface
mögött legyen.azaz Minden hierarchia tetején egy absztrakt osztály
legyen.
GOF2 „Favor object composition over class inheritance!” „Használj objektum összetételt öröklés helyett, ha
csak lehet!” Öröklés: IS-A kapcsolat, könnyen érthető Objektum összetétel: HAS-A kapcsolat,
bonyolultabb Objektum összetétel fajtái:
Aggregáció: Ha meghal a gitáros, nem temetik vele a gitárját.
Kompozició: Ha meghal a gitáros, vele temetik a gitárját.
Az öröklődés mindig kiváltható objektum összetétellel
class A { public void m1() { Console.Write("hello"); }}class B : A { public void m2() { m1(); } }class Program { static void Main(string[] a) { B b = new B(); b.m2(); }}
class A { public void m1() { Console.Write("hello"); }}class B { A a = new A(); public void m2() { a.m1(); }}class Program { static void Main(string[] a) { B b = new B(); b.m2(); }}
GOF2 következményei Öröklést kerülni kell. Rugalmasabb, de nehezebben érthető
lesz a kód. Lehetőséget add arra, hogy futási időben
injektáljunk be felelőséget.
A GOF2-nek ismerjük az előnyeit és hátrányait, de nem tudjuk, mikor kell használni!!!
Tiszta kód
SRP - Single Responsibility Principle „A class should have only one reason to
change” „Az osztályoknak csak egy oka legyen a
változásra”
Programozás technológia elve: „A program kódja állandóan változik”
Az SRP azt mondja ki, hogy egy változás hatására csak egy osztály változzon meg.
SRP következményei Kerüljük a MacsKuty típusú osztályokat:
Akkor is megváltozik, ha kiderül, hogy a Kutya nem csak ugatni tud,
És akkor is megváltozik, ha kiderül, hogy a Macska nem csak egerészni tud.
Sok-sok unit teszt alkalmazása: TDD – Test Driven Develpment
Használjuk Aspektus-Orientált Programozást pl. logolásra, jogosultság ellenőrzésre
Egy összefüggés: SRP ~ GOF1 A GOF1 megszegése gyakran az SRP
megszegéséből ered: Ha egy osztály nem teljesen fedi le a
fellelőség köreit, akkor egy másik osztálynak kell megvalósítani ezeket. Ehhez viszont ismernie kell az eredeti osztály megvalósítását, tehát megszegjük a GOF1-et.
OCP - Open-Closed Principle „Classes should be open for extension,
but closed for modification” „Az osztályok legyen nyitottak a
bővítésre, de zártak a módosításra”azaz „Az osztály hierarchia legyen nyitott a
bővítésre, de zárt a módosításra”
OCP megszegésére utaló jelek Bonyolult if – else if vagy switch
szerkezetek. Override használata.
Csak absztrakt és hook metódusok felülírását engedi.
OCP megszegése class Alakzat { public const int TEGLALAP = 1; public const int KOR = 2; int tipus; public Alakzat(int tipus) { this.tipus = tipus; } public int GetTipus() { return tipus; } } class Teglalap : Alakzat{Teglalap():base(Alakzat.TEGLALAP){}} class Kor : Alakzat{ Kor():base(Alakzat.KOR){} } class GrafikusSzerkeszto { public void RajzolAlakzat(Alakzat a) { if (a.GetTipus() == Alakzat.TEGLALAP) RajzolTeglalap(a); else if (a.GetTipus() == Alakzat.KOR) RajzolKor(a); } public void RajzolKor(Kor k) { /* … */ } public void RajzolTeglalap(Teglalap t) { /* … */ } }
DLP - Decision Lifting Principle „Öröklést csak döntés kiemelésre
használj!” „Use inheritance only for decision
lifting!”
DLP megszegésére utaló jelek: Ismétlődő if – else if szerkezetek. Ismétlődő switch szerkezetek.
DLP megszegése class Alakzat { public const int TEGLALAP = 1; public const int KOR = 2; int tipus; public Alakzat(int tipus) { this.tipus = tipus; } public int GetTipus() { return tipus; } } class Teglalap : Alakzat{Teglalap():base(Alakzat.TEGLALAP){}} class Kor : Alakzat{ Kor():base(Alakzat.KOR){} } class GrafikusSzerkeszto { public void RajzolAlakzat(Alakzat a) { if (a.GetTipus() == Alakzat.TEGLALAP) RajzolTeglalap(a); else if (a.GetTipus() == Alakzat.KOR) RajzolKor(a); } public void RajzolKor(Kor k) { /* … */ } public void RajzolTeglalap(Teglalap t) { /* … */ } }
DLP betartása abstract class Alakzat{ public abstract void Rajzol(); } class Teglalap : Alakzat { public override void Rajzol() { /* téglalapot rajzol */ } } class Kor : Alakzat { public override void Rajzol() { /*kört rajzol */ } } class GrafikusSzerkeszto { public void RajzolAlakzat(Alakzat a) { a.Rajzol(); } } class Program { public static void Main(String[] args) { Alakzat alak = new Kor(); (new GrafikusSzerkeszto ()). RajzolAlakzat(alakzat); }}
Összefüggés az OCP és a DLP közt Az OCP azt mondja, hogy kerüljük a
bonyolult if – else if szerkezeteket. A DLP azt mondja, hogy kerüljük az
ismétlődő if – else if szerkezeteket. Ugyanakkor meg is mondja, hogyan szüntessük meg az ismétlődést:
Döntéskiemelésselű A bonyolult if – else if szerkezetek is
döntéskiemeléssé degradálhatok egyszerű példányosítássá.
Összefüggés a GOF2 és a DLP közt
GOF2: „Használj objektum összetételt öröklés helyett, ha csak lehet!”
azaz Hacsak lehet ne használj öröklést!
DLP: „Öröklést csak döntés kiemelésre használj!”
A DLP pontosítja a GOF2-t, hiszen megmondja, mikor kell öröklést használni, egyébként pedig objektum összetételt kell használni.
Összefoglalás Nagyon sok tervezési alapelv van. Van amelynél tudható, hogy milyen
esetben hogyan kell átalakítani a programot: GOF1, OCP, DLP.
Van amelynél nem tudható, hogy kell-e használni a konkrét esetben, habár sok elméleti előnnyel jár: GOF2, SRP.
Bevezettünk egy új tervezési alapelvet, a DLP-t, amely megmondja mely esetekben nem használandó a GOF2.
KÖSZÖNÖM A FIGYELMET!
Email címek:Kusper Gábor: gkusper@aries.ektf.huMárien Szabolcs: szabolcs.marien@wit-sys.hu
Néhány összefüggés Ha úgy sértjük meg az SRP-t, hogy egy osztály
nem teljesen fedi le a fellelőség köreit, akkor egy másik osztálynak kell megvalósítani ezeket. Ehhez viszont ismernie kell az eredeti osztály megvalósítását, tehát megszegjük a GOF1-et.
Ha úgy sértjük meg az SRP-t, hogy egy osztály több felelőségi kört is lefed, akkor megszegjük a GOF2-öt, mert a két felelőséget szét lehetne szedni két osztályra, amit egy harmadik foghatna össze objektum összetétellel.
top related