Wątek przeniesiony 2022-06-21 17:19 z Kosz przez Adam Boduch.

Strategia w programowaniu obiektowym

0

Dekorator może przyjąć obiekt, który przyjmuje np int albo string, powiedzmy.

Może, ale nie musi, tak samo jak i strategia.

Czy jest użyte słowo class w kodzie?" - jeśli tak, to według @omenomn2 kod jest obiektowy.

Tylko, że to słowo class nie zostaje użyte od czapy, ono coś oznacza.

Jego wystąpienie nie jest warunkiem wystarczajacym, żeby możnabyło coś nazwać paradygmatem obiektowym.

Ale to co się za nim kryje już tak.

Jeżeli szukasz, czegoś co definiuje ostatecznie to czy kod jest obiektowy, to idziesz złym tropem, bo to na pewno nie jest wypełniony konstruktor w każdym jednym przypadku.

0
omenomn2 napisał(a):

Jego wystąpienie nie jest warunkiem wystarczajacym, żeby możnabyło coś nazwać paradygmatem obiektowym.

Ale to co się za nim kryje już tak.

Nie.

Chociażby dlatego że w klasie możesz mieć funkcje statyczne, które z definicji są obiektowe. Więc nie - "Samo to że mam class nie jest wystarczające, żeby nazwać kod obiektowym". Musisz spełnić więcej wymagań.

1

Chociażby dlatego że w klasie możesz mieć funkcje statyczne, które z definicji są obiektowe. Więc nie - "Samo to że mam class nie jest wystarczające, żeby nazwać kod obiektowym". Musisz spełnić więcej wymagań.

Są wzorce obiektowe, które wykorzystują funkcje statyczne.
Serio masz jakiś wypaczony obraz tego czym jest programowanie obiektowe, nawarstwiło Ci się na nie za wiele wymagań.

0
KamilAdam napisał(a):

Ale nie rozmawiamy o tym czy to za dużo tylko o tym czy string jest obiektem. A skoro jest obiektem (jak sam powiedziałeś) to pierwszy kod też jest obiektowy (albo twoja definicja jest błędna)

tylko o tym czy string jest obiektem - to co tutaj piszesz, moim zdaniem, to jest używanie słowa "obiekt" w kontekście tego czy coś jest obiektem w filozofii języka.

Jasne, w Javie jeśli coś spełnia x instanceof Object, to w filozofii Javy jest obiektem. Poodbnie w innych językach. Języki nas nauczyły, że w ramach "swojej logiki" niektóre rzeczy są obiektem, inne nie. I jeśli coś jest jakiegoś typu, jak np Object, String, etc. to że takie coś jest lub nie jest obietem.

str w Pythonie, sam w sobie może być obiektem (pythonowym jak i OOP). Ale inne obiekty mogą go użyć niezgodnie z paradygmatem obiektowym.. Wtedy ten kod nie będzie obiektowy.

6

@Riddle: To dzielisz obiekty na lepsze i gorsze? W kraju, który tyle wycierpiał z powodu wojny?

A w temacie, czy kod:

class PictureWriter(val pictureEncoder:PictureEncoder){
  fun savePicture(File pictureFile){
    when(pirtureFile.extension){
      when "png" -> pictureEncoder.imageFormat = PngEncoder()
      when "jpg" -> pictureEncoder.imageFormat = JpegEncoder(quality=80)
    } 
    writeFile(pictureFile, pictureEncoder.encode(pictureFile.bytes))
  }
  private fun writeFile(....)
}

Jest według ciebie obiektowy, czy nie jest? Albo czy jest dla jpg (bo strategia przyjmuje parametr), ale nie jest dla png?

0
omenomn2 napisał(a):

Chociażby dlatego że w klasie możesz mieć funkcje statyczne, które z definicji są obiektowe. Więc nie - "Samo to że mam class nie jest wystarczające, żeby nazwać kod obiektowym". Musisz spełnić więcej wymagań.

Są wzorce obiektowe, które wykorzystują funkcje statyczne.
Serio masz jakiś wypaczony obraz tego czym jest programowanie obiektowe, nawarstwiło Ci się na nie za wiele wymagań.

Znowu, używasz okreslenia "obiektowe" w znaczeniu "tego czy ma klasy czy nie". Nie, nie ma szans żeby kod który operował na funkcjach statycznych był obiektowy. (przynajmniej nie w paradygmacie obiektowym).

Jeśli Ty używasz okreslenia "obiektowy", i w tym określeniu możesz mieć kod który ma funkcje statyczne

TO NA PEWNO MÓWISZ O CZYMŚ INNYM, NIŻ TO O CZYM JEST TEN WĄTEK

3
Riddle napisał(a):

Ale inne obiekty mogą go użyć niezgodnie z paradygmatem obiektowym..

Ale co to jest ten paradygmat?
I jak wygląda użycie obiektu niezgodnie z paradygmatem obiektowym?

0
jarekr000000 napisał(a):

Ale Twoja definicja nic nie mówiła o mieszaniu poziomów abstrakcji - mówiła tylko czy można (coś tam, coś tam obiektem) - i pokazałeś, że można.

Mówiła:

Sam to napisałeś nawet:

Riddle napisał(a):
jarekr000000 napisał(a):
Riddle napisał(a):

Kod wtedy jest obiektowy, kiedy dane przekazywane pomiędzy różnymi, bliskimi poziomami abstrakcji (i nie mam tu na myśli metod abstrakcyjnych), może być przedstawiona conajmniej jednym obiektem, który przyjmuje ten dane przez konstruktor.

@Riddle: Czyli każdy kod jest obiektowy? Czy też masz kontrprzykład kiedy dane przekazywane pomiędzy różnymi, bliskimi poziomami abstrakcji (i nie mam tu na myśli metod abstrakcyjnych), NIE MOGĄ być przedstawiona conajmniej jednym obiektem, który przyjmuje ten dane przez konstruktor.

Zapytałeś czy mam kontrprzykład, i ja wtedy pokazałem dwa kody. Jeden obiektowy, jeden nie.

0

Kod wtedy jest obiektowy, kiedy dane przekazywane pomiędzy różnymi, bliskimi poziomami abstrakcji (i nie mam tu na myśli metod abstrakcyjnych), może być przedstawiona conajmniej jednym obiektem, który przyjmuje ten dane przez konstruktor.

Pomijając to że jak czytam tę definicję to mi mózg krwawi bo jest napisana niegramatycznie, to nie ma zdefiniowane bliskimi poziomami abstrakcji. Czy mam rozumieć że str i Filename są daleko poziomami abstrakcji?

0
KamilAdam napisał(a):

Kod wtedy jest obiektowy, kiedy dane przekazywane pomiędzy różnymi, bliskimi poziomami abstrakcji (i nie mam tu na myśli metod abstrakcyjnych), może być przedstawiona conajmniej jednym obiektem, który przyjmuje ten dane przez konstruktor.

Pomijając to że jak czytam tę definicję to mi mózg krwawi bo jest napisana niegramatycznie, to nie ma zdefiniowane bliskimi poziomami abstrakcji. Czy mam rozumieć że str i Filename są daleko poziomami abstrakcji?

Nie. "wyciąganie extensiona" i "wyciąganie mime-type" są odległymi poziomami abstrakcji.

0
piotrpo napisał(a):

tak, to jest zmiana strategii, w zależności od tego zawartość pliku będzie inna, załóżmy, że ten "encoder" coś tam jeszcze robi

No ale możnaby to osiągnąć bez zmiany stanu, po prostu przekazując parametr.

Np tak:

class PictureWriter(val pictureEncoder:PictureEncoder){
  fun savePicture(File pictureFile){
    val imageFormat = when(pirtureFile.extension){
      when "png" -> PngEncoder()
      when "jpg" -> JpegEncoder(quality=80)
    } 
    writeFile(pictureFile, pictureEncoder.encode(imageFormat, pictureFile.bytes))
  }
  private fun writeFile(....)
}

Stąd było moje pytanie, czy ta zmiana stanu była tam konieczna? Bo widzisz, ja przerobiłem kod i zmiany stanu nie ma. Więc czy ten kod który tutaj pokazałem, nadal pasuje do Twojego pytania? czy pozbawiłem go tym jego istoty?

0

@Riddle: Nie pasuje, bo wtedy, to już nie będzie wzorcowa strategia, a tego (niby) dotyczy temat. W znaczeniu, tak wiem, ze da się tak zrobić, ale trzymajmy się blisko wzorca.

0
piotrpo napisał(a):

@Riddle: Nie pasuje, bo wtedy, to już nie będzie wzorcowa strategia, a tego (niby) dotyczy temat.

Riddle napisał(a):

Czyli strategia jest tylko wtedy kiedy zmieniasz stan?

Właśnie też się kurde zastanawiam. W orginalnych papierach jest o ustawianiu strategi przez setter. Czy to musi byc setter czy może być przez konstruktor?
@somekind: co ty o tym myślisz?

0
piotrpo napisał(a):

@jarekr000000, @somekind
Nie jestem pewien, czy Strategia może być HOF. To już czysta sofistyka, ale...
Wzorzec projektowy strategii, to sposób na rozwiązanie określonej klasy problemów, czyli zmiany działania fragmentu programu, w trakcie jego wykonywania, sterowana przez coś z zewnątrz. Oczywiście taki problem występuje niezależnie od języka.
Jednak wzorzec, to nie tylko definicja problemu, ale również zalecane rozwiązanie, które wygląda tak:

Oczywiście, że tak, przecież piszę o tym od początku.

KamilAdam napisał(a):

Wreszcie jakiś konkret.

Padłem xD

Konkretnie wyjaśniam o tym, czym jest strategia w chyba już czwartym ostatnio powstałym wątku na ten temat. Niestety niektórzy ciągle nie są w stanie zajarzyć, ze podróż nad morze to nie jest skrzynia biegów - nawet jeśli gdzieś tam w trakcie tej podróży ta skrzynia biegów jest używana.

Riddle napisał(a):

Podobnie jak masz 99% coverage'a, to nikt nie powie że kod niej est przetestowany, ale nie można też powiedzieć żę jest w pełni przetestowany.

To taki offtop, ale jak widzę 99% coverage, to znaczy, że ktoś skupiał się na procentach, a nie testach, więc zakładam, że w ogóle nic nie jest przetestowane.

Ja teraz nie posługuję się w ogóle określeniami "obiektowy język", i mówię tylko "obiektowy kod" albo "nie obiektowy kod". Nie ma języka który by Cię zmusił żebyś uniezależnił dane od implementacji, zawsze jak się uprzesz, to złamiesz gdzieś paradygmat.

Masz trochę racji, ale podobnie nie ma noża, który by Cię zmusił do krojenia sera. I nożem do sera możesz pokroić mięso. Czy przestanie on być nożem do sera?
Można pisać nieobiektowy kod w obiektowym języku, ale język nadal będzie obiektowy. Bo język obiektowy oznacza, że można w nim programować obiektowo.

A to, że gdzieś tam teoretycznie możesz mieć algorytm, który nie przyjmuje żadnych parametrów (aczkolwiek trudno im sobie to wyobrazić w nieakademickim przykładzie) nie zmienia faktu, że strategia to wzorzec programowania obiektowego.

Niektóre są. Mogę sobie łatwo wyobrazić aplikacje która nie ma absolutnie żądnej logiki w funkcjach statycznych, i spełniająca pozostałe założenia.

Bardzo wątpię. Gdzieś tam na pewno będzie wywołanie jakiegoś statycznego kodu, chociażby z bibliotek frameworka albo systemowych.

1
somekind napisał(a):

Bardzo wątpię. Gdzieś tam na pewno będzie wywołanie jakiegoś statycznego kodu, chociażby z bibliotek frameworka albo systemowych.

To akurat tylko obecnie typowy design w językach javopodobnych, ale nie jest to ograniczenie języka.
Można sobie wyobrazić, że funkcja main() przyjmuje argument typu System, który jest fasadą na kolejne moduły (getIO(), .getThreading() ... etc) i łatwo można się obejśc bez staticów.

Z drugiej strony powstaje pytanie - czym jest konstruktor, jeśli nie pewną formą statica... i koniec.

1

@Riddle:

No moim zdaniem to co pisze @piotrpo to brednie. Czemu niby ustawienie stanu miałoby być kluczowym elementem strategii, albo czemu w niemutowalnych klasach strategia miałby nie mieć racji bytu? Chodzi przecież o dostarczenie implementacji algorytmu.

Jeżeli mówimy o wzorcu, składającym się z problemu i implementacji, to strategia nie jest wyłącznie "wstrzyknięciem algorytmu". Gdyby tak było, to czym różni się od np. obserwatora? A jeżeli olejemy kompletnie wzorzec, to przecież da się taki problem rozwiązać w dowolnym języku Turing complete, chociażby za pomocą drabinki warunków i skoków.

Dla przypomnienia jak wygląda wzorzec:
screenshot-20220623130949.png

0
jarekr000000 napisał(a):

Po prostu zredaguj tą definicję, bo coś miałeś na myśli, ale logicznie wyszło bez sensu. (BTW. robienie takich definicji jest trudne).

No dobra. To spróbjmy kryteria

Moim zdaniem. Kod obiektowy to kod w którym spełniony jest każdy z warunków:

  • Nie występuje deklaracja żadnych funkcji statycznych (ale można ich użyć jako szczegół implementacyjny jakiegoś obiektu, w taki sposób żeby klienci obiektu o nim nie wiedzieli)
  • Dziedziczenie jest używane tylko jako szczegół implementacyjny, nie jako współdzielenie interfejsu
  • Nie występują obiekty, które można bez strat w logice sprowadzić do postaci funkcji (np obiektów które nie przyjmują nic przez parametr konstruktora).
  • Operacje na danych nie powinny być przeprowadzone na więcej niż jednym poziomie abstrakcji (np nie powinno się używać tego samego obiektu do okreslenia extensionu jak i mime'type'u).
    • Dla przykładu, jeśli dostajemy jedną daną (np Pesel) i z niego chcemy odczytać w programie datę urodzenia, wiek oraz płeć, to musimy stworzyć trzy obiekty które dostają ten pesel, jeden pozwala nam odczytać datę urodzenia, jeden wiek, a jeden płeć, i są przekazywane tam, gdzie każde z tych miejsc wymaga tych danych. Jeśli inny obiekt wymaga ich trzech, to powinny zostać skomponowane w czwarty obiekt, z którego można odczytać każdą z tych danych, ale który nie wie nic o peselu.
  • null nie jest używany jako wartość sama w sobie (tylko jest przekazywany jako parametry obiektu, który prezentuje zachowanie sugerujące "brak wartości")
  • Wartości nie są przekazywane bez obiektów (np publiczne stałe).
  • Metoda obiektu zwracająca wartość nie ma side-effectów (zmiany stanu obiektu lub stanu systemu).
  • Metoda zmieniająca stan obiektu lub systemu ma return-type void.
  • Nie zachodzi metaprograming (refleksje, kontenery zależnosci, switch na .class/::class/get_class(), Mickito)
  • Nie występuje rzutowanie typów
  • Nie występuje instanceof (chyba że jako szczegół implementacyjny pojedynczego obiektu, użyte na wartości zwróconej przez biblioteki, bez możliwości ominięcia go. Wtedy taką klasę na której się robi instanceof traktuje się jako gołą daną, i nie jest obiektem w rozumieniu OOP)
  • Klasy są albo final/sealed/nie open, albo abstract/interface.

Możliwe że dopiszę coś więcej, jak o tym pomyślę.

1
Riddle napisał(a):
  • Nie występują obiekty, które można bez strat w logice sprowadzić do postaci funkcji (np obiektów które nie przyjmują nic przez parametr konstruktora).

Ten warunek nie będzie spełniony dla dowolnego obiektu, bo wszystko możesz zamienić na funkcję (parametryKonstruktora, parametry metody) -> (kontekst, rezultat)

7

@Riddle: twoje kryteria są bardzo dziwne. Bardzo mocno mylisz "łamie OOP" z "łamie praktyki, które ja uznaję za dobre praktyki OOP".

Z twoich kryteriów wynika, że nie można zaimplementować stosu w OOP, bo operacja pop() zmienia stan obiektu i zwraca wartość, a według ciebie:

Metoda obiektu zwracająca wartość nie ma side-effectów (zmiany stanu obiektu lub stanu systemu).

0
piotrpo napisał(a):
Riddle napisał(a):
  • Nie występują obiekty, które można bez strat w logice sprowadzić do postaci funkcji (np obiektów które nie przyjmują nic przez parametr konstruktora).

Ten warunek nie będzie spełniony dla dowolnego obiektu, bo wszystko możesz zamienić na funkcję (parametryKonstruktora, parametry metody) -> (kontekst, rezultat)

Nie, np tego nie można:

class FullName {
  FullName(string fullname) {
    this.fullname = fullname;
  }

  firstName() {
     return fullname.split(" ")[0];
  }
  
  surname() {
     return fullname.split(" ")[1];
  }
}

I jesli użyjesz go gdzieś tak:

void jakaśFunkcja(FullName name) {
  WriteLine("Moje imie to " + name.firstName() + ", a nazwisko to " + name.surname());
}

to nie możesz.

wartek01 napisał(a):

@Riddle: twoje kryteria są bardzo dziwne. Bardzo mocno mylisz "łamie OOP" z "łamie praktyki, które ja uznaję za dobre praktyki OOP".

Z twoich kryteriów wynika, że nie można zaimplementować stosu w OOP, bo operacja pop() zmienia stan obiektu i zwraca wartość, a według ciebie:

Metoda obiektu zwracająca wartość nie ma side-effectów (zmiany stanu obiektu lub stanu systemu).

Dokładnie. pop() w stosie jest nieobiektowy. Łamie też CQS.

Żeby był obiektowy powinno się zrobić last = stack.last(); stack.removeLast(); (gdzie removeLast()) zwraca void. Jeśli pop() coś usuwa i zwraca, to nie jest napisany w paradygmacie obiektowym, po prostu.

0
fun firstName(fullName):<Context, Result>{
  return Pair(fullName, fullName.split(" ")[0])
}

fun lastName(fullName)<Context, Result>{
  return Pair(fullName, fullName.split(" ")[1])
}
....
fun jakaśFunkcja(fullName) {
  val a = firstName(fullName)
  val firstName = a.last
  val lastName = lastName(a.first)
....
}

@Riddle: Tak, jest brzydko. Ale się da. I nie ma sensu, bo fullName się nie zmienia, ale tak samo można przekazać cały stan dowolnego obiektu, juz po zmianie.

0

Dokładnie. pop() w stosie jest nieobiektowy. Żeby był obiektowy powinno się zrobić last = stack.last(); stack.removeLast(); (gdzie removeLast()) zwraca void. Jeśli pop() coś usuwa i zwraca, to nie jest napisany w paradygmacie obiektowym, po prostu

@Riddle: Próbowałeś kiedyś programować coś wielowątkowego? Np sytuacja jeden producent, wielu konsumentów. Wszystko synchronizowane kolejką, ale konsumenci ściągają dane z kolejki kto pierwszy ten lepszy. I teraz spróbuj zaimplemntować to w OOP z last = stack.last(); stack.removeLast(). Czy to znaczy że OOP nie nadaje się do programowania wielowątkowania, Czy nie da się stworzyć kolejki do synchronizacji watków w OOP?

0
KamilAdam napisał(a):

Dokładnie. pop() w stosie jest nieobiektowy. Żeby był obiektowy powinno się zrobić last = stack.last(); stack.removeLast(); (gdzie removeLast()) zwraca void. Jeśli pop() coś usuwa i zwraca, to nie jest napisany w paradygmacie obiektowym, po prostu

@Riddle: Próbowałeś kiedyś programować coś wielowątkowego? Np sytuacja jeden producent, wielu konsumentów. Wszystko synchronizowane kolejką, ale konsumenci ściągają dane z kolejki kto pierwszy ten lepszy. I teraz spróbuj zaimplemntować to w OOP z last = stack.last(); stack.removeLast(). Czy to znaczy że OOP nie nadaje się do programowania wielowątkowania, Czy nie da się stworzyć kolejki do synchronizacji watków w OOP?

Twoje pytanie tak na prawdę brzmi "Czy to znaczy że CQS nie nadaje się do programowania wielowątkowania, Czy nie da się stworzyć kolejki do synchronizacji watków w CQS?"

2
Riddle napisał(a):
KamilAdam napisał(a):

Dokładnie. pop() w stosie jest nieobiektowy. Żeby był obiektowy powinno się zrobić last = stack.last(); stack.removeLast(); (gdzie removeLast()) zwraca void. Jeśli pop() coś usuwa i zwraca, to nie jest napisany w paradygmacie obiektowym, po prostu

@Riddle: Próbowałeś kiedyś programować coś wielowątkowego? Np sytuacja jeden producent, wielu konsumentów. Wszystko synchronizowane kolejką, ale konsumenci ściągają dane z kolejki kto pierwszy ten lepszy. I teraz spróbuj zaimplemntować to w OOP z last = stack.last(); stack.removeLast(). Czy to znaczy że OOP nie nadaje się do programowania wielowątkowania, Czy nie da się stworzyć kolejki do synchronizacji watków w OOP?

Twoje pytanie tak na prawdę brzmi "Czy to znaczy że CQS nie nadaje się do programowania wielowątkowania, Czy nie da się stworzyć kolejki do synchronizacji watków w CQS?"

Zgadza się, ale z twojej definicji OOP zrozumiałem że CQS jest warunkiem koniecznym OOP. WIęc jeśli nie da się programować wielowątkowo używając CQS, to nie da się też programować wielowątkowo używając OOP

0
KamilAdam napisał(a):
Riddle napisał(a):
KamilAdam napisał(a):

Dokładnie. pop() w stosie jest nieobiektowy. Żeby był obiektowy powinno się zrobić last = stack.last(); stack.removeLast(); (gdzie removeLast()) zwraca void. Jeśli pop() coś usuwa i zwraca, to nie jest napisany w paradygmacie obiektowym, po prostu

@Riddle: Próbowałeś kiedyś programować coś wielowątkowego? Np sytuacja jeden producent, wielu konsumentów. Wszystko synchronizowane kolejką, ale konsumenci ściągają dane z kolejki kto pierwszy ten lepszy. I teraz spróbuj zaimplemntować to w OOP z last = stack.last(); stack.removeLast(). Czy to znaczy że OOP nie nadaje się do programowania wielowątkowania, Czy nie da się stworzyć kolejki do synchronizacji watków w OOP?

Twoje pytanie tak na prawdę brzmi "Czy to znaczy że CQS nie nadaje się do programowania wielowątkowania, Czy nie da się stworzyć kolejki do synchronizacji watków w CQS?"

Zgadza się, ale z twojej definicji OOP zrozumiałem że CQS jest warunkiem koniecznym OOP. WIęc jeśli nie da się programować wielowątkowo używając CQS, to nie da się też programować wielowątkowo używając OOP

Tak, jesli nie da się w CQS, to nie da się też w OOP, a jeśli da się w CQS, to da się też w OOP.

Mogę z tym żyć.

Bo to co teraz robisz, Twój arugment to jest zrobienie czegoś takiego:

  • Wymyśl standardowy scenariusz (nie obiektowy), np taki ze stosem
  • Usłysz zasady obiektowe
  • Przerób standardowy nieobiektowy scenariusz, względem zasad obiektowych
  • Dostań coś co nie ma sensu
  • Krytykuj rezultat.

Coś co opisywałem dokładnie tutaj: Strategia w programowaniu obiektowym

Jakbym wziął nie funkcyjny kod (imperatywny and/or proceduralny kod), i wprowadził do niego zasadę "nie redefiniuj zmiennych", i ktoś po prostu ślepo wprowadziłby te zasady do kodu, to też dostałbyś głupi wynik, który mógłbyś krytykować.

Kluczem jest tutaj nie a) weź nieobiektowe rozwiązanie b) próbuj przerobić go na OP c) krytykuj wynik; tylko rozwiązaniem byłoby raczej - a) Zaprojektuj obiektowe rozwiązanie problemu o którym mówisz. I to rozwiązanie, raczej nie wyglądałoby jak stos.

Bezowocnym jest zmienić paradygmat, i spodziewać się efektu podobnego do tego przed zmianą paradygmatu

To jest cały sens. Zmienić paradygmat, to zmienić sposób implementacji róznych rozwiązań. To nie jest po prostu "ślepe podporządkowanie się pod arbitralne zasady".

4
Riddle napisał(a):
jarekr000000 napisał(a):

Po prostu zredaguj tą definicję, bo coś miałeś na myśli, ale logicznie wyszło bez sensu. (BTW. robienie takich definicji jest trudne).

No dobra. To spróbjmy kryteria

Moim zdaniem. Kod obiektowy to kod w którym spełniony jest każdy z warunków:

  • Nie występuje deklaracja żadnych funkcji statycznych (ale można ich użyć jako szczegół implementacyjny jakiegoś obiektu, w taki sposób żeby klienci obiektu o nim nie wiedzieli)
  • Dziedziczenie jest używane tylko jako szczegół implementacyjny, nie jako współdzielenie interfejsu
  • Nie występują obiekty, które można bez strat w logice sprowadzić do postaci funkcji (np obiektów które nie przyjmują nic przez parametr konstruktora).
  • Operacje na danych nie powinny być przeprowadzone na więcej niż jednym poziomie abstrakcji (np nie powinno się używać tego samego obiektu do okreslenia extensionu jak i mime'type'u).
    • Dla przykładu, jeśli dostajemy jedną daną (np Pesel) i z niego chcemy odczytać w programie datę urodzenia, wiek oraz płeć, to musimy stworzyć trzy obiekty które dostają ten pesel, jeden pozwala nam odczytać datę urodzenia, jeden wiek, a jeden płeć, i są przekazywane tam, gdzie każde z tych miejsc wymaga tych danych. Jeśli inny obiekt wymaga ich trzech, to powinny zostać skomponowane w czwarty obiekt, z którego można odczytać każdą z tych danych, ale który nie wie nic o peselu.
  • null nie jest używany jako wartość sama w sobie (tylko jest przekazywany jako parametry obiektu, który prezentuje zachowanie sugerujące "brak wartości")
  • Wartości nie są przekazywane bez obiektów (np publiczne stałe).
  • Metoda obiektu zwracająca wartość nie ma side-effectów (zmiany stanu obiektu lub stanu systemu).
  • Metoda zmieniająca stan obiektu lub systemu ma return-type void.
  • Nie zachodzi metaprograming (refleksje, kontenery zależnosci, switch na .class/::class/get_class(), Mickito)
  • Nie występuje rzutowanie typów
  • Nie występuje instanceof (chyba że jako szczegół implementacyjny pojedynczego obiektu, użyte na wartości zwróconej przez biblioteki, bez możliwości ominięcia go. Wtedy taką klasę na której się robi instanceof traktuje się jako gołą daną, i nie jest obiektem w rozumieniu OOP)
  • Klasy są albo final/sealed/nie open, albo abstract/interface.
    Możliwe że dopiszę coś więcej, jak o tym pomyślę.

No to jedziemy.
Rzucam kod hipotetycznie obiektowy

 10 REM Basic version of 99 bottles of beer
 20 REM Modified by M. Eric Carr ([email protected])
 30 REM from prior version found on this site.
 40 REM (Modified to correct "1 bottle" grammar)
 50 FOR X=99 TO 1 STEP -1
 60 PRINT X;"bottle";
 70 IF X<>1 THEN PRINT "s";
 80 PRINT " of beer on the wall,";X;"bottle";
 90 IF X<>1 THEN PRINT "s";
100 PRINT " of beer"
110 PRINT "Take one down and pass it around,"
120 PRINT X-1;"bottle";
130 IF X<>1 THEN PRINT "s";
140 PRINT " of beer on the wall"
150 NEXT

Na razie nie znajduję, które punkty łamie (ale może jestem nieuważny).

0
jarekr000000 napisał(a):

No to jedziemy.
Rzucam kod hipotetycznie obiektowy

 10 REM Basic version of 99 bottles of beer
 20 REM Modified by M. Eric Carr ([email protected])
 30 REM from prior version found on this site.
 40 REM (Modified to correct "1 bottle" grammar)
 50 FOR X=99 TO 1 STEP -1
 60 PRINT X;"bottle";
 70 IF X<>1 THEN PRINT "s";
 80 PRINT " of beer on the wall,";X;"bottle";
 90 IF X<>1 THEN PRINT "s";
100 PRINT " of beer"
110 PRINT "Take one down and pass it around,"
120 PRINT X-1;"bottle";
130 IF X<>1 THEN PRINT "s";
140 PRINT " of beer on the wall"
150 NEXT

Na razie nie znajduję, które punkty łamie (ale może jestem nieuważny).

To be honest, to ja powiedziałbym że on jest obiektowy. Iteracja, if i w sumie tyle. Także, w moim projekcie, powiedziałbym że to może uchodzić za obiektowy kod. Moim zdaniem ten kod jest obiektowy, mimo że nie ma obiektów w nim. Nie ma nic, co możnaby sensownie wydzielić.

Podobnego argumentu użyłbym, żeby spytać: czy ten kod jest funkcyjny:

print(2 + 3)

Moim zdaniem chyba tak, mimo że nie ma deklaracji funkcji w nim, bo nie ma co sensownie z niego wydzielić.

Idąc dalej tą karuzelą śmiechu, można założyć że pusty program (0 linijek, nic nie robi, tylko się bierze i wyłącza) pasuje do każdego paradygmatu świata

2
Riddle napisał(a):
jarekr000000 napisał(a):

No to jedziemy.
Rzucam kod hipotetycznie obiektowy

 10 REM Basic version of 99 bottles of beer
 20 REM Modified by M. Eric Carr ([email protected])
 30 REM from prior version found on this site.
 40 REM (Modified to correct "1 bottle" grammar)
 50 FOR X=99 TO 1 STEP -1
 60 PRINT X;"bottle";
 70 IF X<>1 THEN PRINT "s";
 80 PRINT " of beer on the wall,";X;"bottle";
 90 IF X<>1 THEN PRINT "s";
100 PRINT " of beer"
110 PRINT "Take one down and pass it around,"
120 PRINT X-1;"bottle";
130 IF X<>1 THEN PRINT "s";
140 PRINT " of beer on the wall"
150 NEXT

Na razie nie znajduję, które punkty łamie (ale może jestem nieuważny).

To be honest, to ja powiedziałbym że on jest obiektowy. Iteracja, if i w sumie tyle. Także, w moim projekcie, powiedziałbym że to może uchodzić za obiektowy kod. Moim zdaniem ten kod jest obiektowy, mimo że nie ma obiektów w nim. Nie ma nic, co możnaby sensownie wydzielić.

No to mamy wreszcie jakąś spójną definicję obiektowości i cieszy mnie, że mój ukochany BASIC z C64 się załapał (nie wiem czy każdy program w BASICU, ale z tego co widzę powyżej to dużo się załapie)

Podobnego argumentu użyłbym, żeby spytać: czy ten kod jest funkcyjny:

print(2 + 3)

A to akurat zależy. Zależy jak wygląda sygnatura funkcji print.
Jeśli print zwraca void czy coś w tym stylu, to można domniemywać, że nie jest to kod funkcyjny.

0
jarekr000000 napisał(a):

No to mamy wreszcie jakąś spójną definicję obiektowości i cieszy mnie, że mój ukochany BASIC z C64 się załapał (nie wiem czy każdy program w BASICU, ale z tego co widzę powyżej to dużo się załapie)

Od razu mówię, że według mnie nie ma czegośtakiego jak "język obiektowy", pisałem już o tym wyzej.

Mogę Ci powiedzieć czy kod który napisałeś jest obiektowy czy nie.

Ja o tym myślę w taki sposób. Czy istnieje coś takiego jak bezpieczny język? Taki język, w którym da się napisać tylko bezpieczny kod, a niebezpiecznych się nie da? Moim zdaniem nie ma czegoś takiego.

Podobnie, jak nie ma języków obiektowych, w których da się napisać kod tylko obiektowy, a nie obiektowych się nie da.

5
Riddle napisał(a):
jarekr000000 napisał(a):

No to mamy wreszcie jakąś spójną definicję obiektowości i cieszy mnie, że mój ukochany BASIC z C64 się załapał (nie wiem czy każdy program w BASICU, ale z tego co widzę powyżej to dużo się załapie)

Od razu mówię, że według mnie nie ma czegośtakiego jak "język obiektowy", pisałem już o tym wyzej.

Mogę Ci powiedzieć czy kod który napisałeś jest obiektowy czy nie.

Oczywiście.
Aczkolwiek, zgodnie z tą definicją to w zasadzie nie da się napisać w tym BASICu kodu, który nie byłby obiektowy. A to mi wystarcza. Oznacza, że byłem programistą obiektowym zanim to było modne.

1 użytkowników online, w tym zalogowanych: 0, gości: 1