Co sądzisz o OOP?

Co sądzisz o OOP?
Satanistyczny Awatar
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 750
1

Ogromnie Obrzydliwy Paradygmat

szatkus1
  • Rejestracja: dni
  • Ostatnio: dni
4

Propsy za przemyślaną ankietę 👍🏻

screenshot-20240523214057.png

GO
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 358
1

Ja nigdy nie rozumiem o co chodzi z tym OOP.

W C++ dodali struktury tak, że metody są przyczepione do struktury i nie trzeba szukać.
Ja lubię OOP nie wiem czy o to chodzi, ale dobrze jest jak masz MemoryManagment i po prostu jakaś klasa odpowiada za to, lubię struktrualnie pisać, ale jak jest kod ładnie upakowany edytor umie podpowiadać bo jak są struktury to nie umie, ale od c++ struktura === klasa, a na poziomie assemblera to i tak zawsze było tym samym, nigdy nie było różnicy tylko łatwiej idzie tym zarządzać.

W C++ struktura i klasa czyli obiekt jak się utworzy z tej klasy jest tym samym, edytor czyli language server umie podpowiadać dobrze jak wie, że dane są ze sobą ściśle powiązane czyli jak w obiekcie.
W C++ struktura też może mieć metody jak w obiekcie czyli edytor możę łatwo przewidywać jakie funkcje dla danej struktury możesz użyć.

LukeJL
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 8488
0
.GodOfCode. napisał(a):

language server umie podpowiadać dobrze jak wie, że dane są ze sobą ściśle powiązane czyli jak w obiekcie.

Language server to protokoł, a nie coś absolutnego. Jeśli istniejąca do danego języka implementacja language servera jest słaba, to można zrobić lepszą.

W C++ struktura też może mieć metody jak w obiekcie czyli edytor możę łatwo przewidywać jakie funkcje dla danej struktury możesz użyć.

Tutaj trzeba spojrzeć szerzej. To, o czym piszesz, to ograniczenia toolingu, a nie paradygmatu.

Pisząc w C++ jesteś ograniczony składnią C++, która wywiera wpływ na to, jak to jest dalej parsowane i jak dobry masz tooling. Być może w innym, bardziej statycznie typowanym, języku będziesz mieć lepszy tooling.

Chyba, że mówisz po prostu o tym, że klasa jest przestrzenią nazw i dając foo. już wiadomo, że trzeba podpowiedzieć coś związanego z foo. a nie totalnie wszystko. Ale... dla mnie to jest zagadnienie poboczne do całego paradygmatu. W programowaniu proceduralnym też możesz mieć przestrzenie nazw.

KR
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 168
0

Czy DDD jest oparte na OOP? DDD też nie lubimy?

jarekr000000
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: U krasnoludów - pod górą
  • Postów: 4712
3
krsp napisał(a):

Czy DDD jest oparte na OOP? DDD też nie lubimy?

DDD to dopiero naprawdę nie lubimy, OOP przy tym to pestka.

markone_dev
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 833
2
krsp napisał(a):

Czy DDD jest oparte na OOP?

Nie. DDD to zestaw wzorców i praktyk, nie implementacji. Strategiczne DDD nie ma nic wspólnego z kodem. W taktycznym DDD nie ma znaczenia w jakim paradygmacie piszesz agregaty, value objecty czy encje. Jak poszukasz to znajdziesz przykłady implementacji DDD w językach funkcyjnych, bo DDD to sposób myślenia o architekturze aplikacji, nie konkretnej technologii czy metodyce programowania.

CZ
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2553
0

Po co wymyślać coś nowego skoro klienci i tak kupią więcej RAMu, żeby program mógł przerzucać ogromnymi obiektami xd.

jarekr000000
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: U krasnoludów - pod górą
  • Postów: 4712
2
Czitels napisał(a):

Po co wymyślać coś nowego skoro klienci i tak kupią więcej RAMu, żeby program mógł przerzucać ogromnymi obiektami xd.

Jeśli jakoś przespałeś ostatnie kilka lat to mały update - obecnie rzadko kiedy klienci kupują RAM. Wynajmują sobie, a nawet to my im wynajmujemy - żeby nie musieli się martwić.
1.5 terabajta wystarczy każdemu.

KamilAdam
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Silesia/Marki
  • Postów: 5550
5

W Javie mam wrażenie iż nigdy OOP nie pyknął. JEE i a później Spring promowały anemiczny model dziedziny, encje i serwisy, później encje i serwisy bezstanowe. Z OOP ma to tylko tyle wspólnego iż serwisy mają często interfejs. Jakby w Javie zakazano dziedziczyć po klasach to pewnie by w 75% projektów nie zauważyli. A przecież od razu widać iż encje i serwisy to już prawie, w zasadzie rekordy i modułu z funkcjami. A więc enterprisowym projektom javowym bliżej do FP niż do OOP. Może jakbym został C#powcem to bym zrozumiał OOP, ale tak to nie mialem potrzeby

UPDATE w javie jedyne OOP jakie spotkałem to to iż trzeba umieć recytować SOLID na rekrutacjach. Nie wiem po co, ale tech liderzy Javy lubią słuchać recytacji SOLID

WeiXiao
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5227
1

OOP to najbardziej wpływowy zbiór konceptów dot. modelowania fragmentów świata rzeczywistego za pomocą języków programowania.

Umożliwił on przez ostatnie dekady milionom programistów wykonanie cyfrowej transformacji i przeniesienie wielu procesów w świat komputerów m.in ze względu na swoją prostotę i łatwość mapowania konceptów rzeczywistych z ich cyfrowym modelem (oczywiście w 99% uproszczonym modelem).

OOP jak każdy inny paradygmat może być różnie interpretowany, dlatego widzimy różnice w OOPie pomiędzy różnymi językami programowania implementującymi w różnym stopniu ten paradygmat (np. C++owy friend).

Czy krytyka OOP jest zasadna? uważam że nie do końca, OOP ma swoje wady np. zbyt duże pchanie się w koncepty dziedziczenia którymi łatwo sobie zrobić krzywdę, jednakże koniec końców wyszedł na PLUS dla świata.

Nagonka na OOP bardziej wygląda tak, że kilku hipsterów naczytało się na 4p dwóch czy trzech pozytywnych postów o innych paradygmatach, o których zapomnieli 2 flaszki po zaliczonej kartkówce z "Paradygmatów programowania" w koledżu, ale teraz chcą się pobrandzlować :D

Riddle
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 10227
2

Zacznijmy od tego że dwadzieścia osób kiedy mówi o OOP to ma na myśli różne rzeczy. Geneza , zaszłośc historyczne, osobiste uprzedzenia , dopowiedzenia.

Rozmowa o tym bez jakichś konkretnych określeń o czym mowa - nie ma sensu.

KamilAdam
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Silesia/Marki
  • Postów: 5550
0
Riddle napisał(a):

Rozmowa o tym bez jakichś konkretnych określeń o czym mowa - nie ma sensu.

A teraz skandujemy - Definicja, definicja, definicja!

DH
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 32
4

Z takimi tematami jest jak z magia. Magik przybywa do firmy aby prawic prawdy objawione, wszyscy kiwaja glowami, a po szkoleniu wracamy do tego, co bylo.

Riddle
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 10227
5
KamilAdam napisał(a):
Riddle napisał(a):

Rozmowa o tym bez jakichś konkretnych określeń o czym mowa - nie ma sensu.

A teraz skandujemy - Definicja, definicja, definicja!

Nie chodzi mi o definicję, tylko o jakieś przekonanie że mówimy o tym samym.

Wyobrażam sobie że jak ktoś używa określenia "OOP", to zależnie od swojej wiedzy, umiejętności, i tego się uczył może mieć na myśli, paradygmat, ale może ten paradygmat rozumieć różnorako, np.:

  • Może to rozumieć tak, że po prostu otwiera projekt, widzi same klasy i myśli: "o, to jest OOP"
  • Może to rozumieć jak Robert Martin, że OOP to jest "dyscyplina nałożona na niebezpośredni transfer kontroli"
  • Może mieć w głowie slogany: enkapsulacja, dziedziczenie, polimorfizm
  • Może to rozumieć przez pryzmat języków Java i C# gdzie (przynajmniej we wczesnych wersjach) kod dało się tylko pisać jako członek klasy
  • Może po prostu woleć pisać class niż function, i twierdzi że to jest OOP
  • Może myśleć o milionie wzorców, dekoratory, kompozyt, etc.
  • Może na to patrzeć przez pryzmat tych dziwnych relacji is-a, has-a
  • Może utożsamia OOP z interfejsami z javy które potem poszły na inne języki (i twierdzi że jak jest interface to jest to polimorfizm, a duck-typing już polimorfizmem nie jest).
  • Jeszcze inni mogą myśleć że OOP jest tylko wtedy kiedy wystąpi słowo class w kodzie, a jeśli zrobimy np funkcje w JS która zwraca dictinoary z domknięciami to już obiektem nie jest (bo jest function zamiat class).
  • Może do tego podchodzić niskopoziomowo, i rozumieć to tak że obiekt to jest cokolwiek co żyje na stercie.
  • Może na to patrzeć że dziedziczenie da się załatwić strukturami, a enkapsulację funkcjami, więc jedyne co wnosi OOP "nowego" to jest polimorfizm (z tą różnicą że polimorfizm da się też ogarnąć anonimowymi funkcjami które zacierają granice między obiektem i funkcją).

Nie mówiąc o tym że ktoś może mieć milion uprzedzeń i naleciałości. Ja osobiście uważam że tylko ostatnia pozycja jest prawdziwa, a pozostałe nie; ale to jest moja opinia. Inni mogą mieć inne.

Więc moim zdaniem ta dyskusja nie ma sensu, bez sprecyzowania o "które" OOP chodzi. Określenie OOP jest bardzo popularne, i ludzie bardzo łatwo lubią podpinać swoje przekonania pod taki popularny banner.

CZ
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2553
0
dr.hard napisał(a):

Z takimi tematami jest jak z magia. Magik przybywa do firmy aby prawic prawdy objawione, wszyscy kiwaja glowami, a po szkoleniu wracamy do tego, co bylo.

To jest dość życiowe xd Szczególnie na tych wszystkich szkoleniach z wzorców, wielowątkowości itd.

SL
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1023
0

OOP to rozmyte podejście, które w sumie nie oznacza nic przez to, że OOP jest wszędzie. Idąc od najbardziej (według mnie) oczywistości do bardziej kontrowersyjnych:

  • OOP to paradygmat, który ułatwia łatwe łączenie kodu z danymi. Takie coś da się osiągnąć w każdym języku. Najlepszym przykładem są generyczne struktury danych, które mają złożony stan wewnętrzny, który musi być modyfikowany i czytany w określony sposób. Niezależnie od paradygmatu czy to imperatywny czy funkcyjny: enkapsulacja i wyznaczone funkcje do czytania/modyfikowania to konieczność
  • OOP to paradygmat, który pozwala na jakikolwiek polimorfizm pod postacią jakiegoś interfejsu. Takie coś mamy w praktycznie każdym nowoczesnym języku. Haskell pozwala na statyczny polimorfizm. Dobrym kontr przykładem jest C, który pozwala na polimorfizm dynamiczny (poprzez strukturę zawierającą wskaźniki do funkcji), ale jest to nie wygodne, więc to może być argument, że C nie jest OOP
  • OOP to paradygmat z enkapsulacją, Enkapsulacja IMO jest dobra dla dowolnego bytu czy to klasa, struktura czy pojedyncza funkcja, więc odrzucam ten argument
  • OOP to paradygmat, która ma dynamiczny polimorfizm. Argumentem przeciwnym jest to, że możemy bardzo łatwo zamienić taki dynamiczny polimorfizm na statyczny i według mnie nie stracimy magii OOP. Dobrym przykładem jest Rust, gdzie bardzo łatwo żonglować jednym i drugim rodzajem według potrzeb
  • OOP to język, który ma klasy. Dobrym kont przykładem jest Go, gdzie metody i interfejsy możemy podpiąc pod każdy typ. Choć najczęściej są tą rzeczywiście struktury, to da się napisać kod, wyglądający jak OOP, używać polimorfizmu i nie
  • OOP to paradygmat, który ma dziedziczenie. Według mnie to nie prawda, bo każdy przykład dziedziczenia można zamienić na interfejs + kompozycja (punkt 2), gdzie popularnym stwierdzeniem jest to, że taka konstrukcja jest po prostu lepsza z wielu różnych powodów: większa rozszerzalność, lepsza enkapsulacja, bardziej eleganckie z uwagi na użycie mniejszej ilości ficzerów języka
  • OOP to paradygmat, który means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things. Mało języków wspiera taki paradygmat, bo extreme late-binding i messaging sprawiają, że taka implementacja jest wolna i dynamicznie typowana a w dzisiejszych czasach bardzo kładziemy na wydajność i statyczną poprawność programu

Moja opinia: zgadzam się w 100% tylko z dwoma pierwszymi punktami. Niestety (albo stety) każdy nowoczesny język według tej wykładni jest OOP.

Wydaje mi się, że język, które ewoluuje zgodnie z tradycją OOP jest OOP cokolwiek to miałoby znaczyć. Ewolucja w każdej dziedzinie nie wyklucza radykalnych zmian, które mogą sprawić, że następca jest dalej od oryginału niż mogłoby się to wydawać na pierwszy rzut oka. Pies i delfin są dużo bardziej zgodni genetycznie, ale delfin swoim stylem życia i przystowaniem bardziej przypomina rybę z uwagi na to jak zadziałała ewolucja w tym konkretnym przypadku

Satanistyczny Awatar
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 750
1
WeiXiao napisał(a):

OOP to najbardziej wpływowy zbiór konceptów dot. modelowania fragmentów świata rzeczywistego

Skończyłem czytać w tym miejscu.

WeiXiao
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5227
0
Satanistyczny Awatar napisał(a):
WeiXiao napisał(a):

OOP to najbardziej wpływowy zbiór konceptów dot. modelowania fragmentów świata rzeczywistego

Skończyłem czytać w tym miejscu.

cuz? paradygmat zbiera do kupy koncepty, te koncepty są implementowane przez języki jako takie "basic primitives", które następnie są używane do modelowania problemów/fragmentów świata przez programistów.

Allegro/ebay, uber, tinder, stock market, facebook, etc... To wszystko to koncepty/procesy/zjawiska które zostały w jakimś stopniu przeniesione z świata rzeczywistego do komputera, poprzez ich zamodelowanie.

RJ
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 480
0

Piękna sprawa i tyle. Nie mielibyście gdzie narzekać gdy nie OOP.

YA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 252
1

Co to do (...) jest OOP? To jedno z najbardziej rozmytych określeń w programowaniu, każdy rozumie przez nie co innego. Chyba OOP jest jeszcze bardziej wieloznaczne niz FP, a już samo FP, wbrew pozorom, ma wiele defnicji.

MOIM ZDANIEM najbardziej użyteczna definicja OOP byłaby chyba taka: Jest to paradygmat zdefiniowany przez klasyków takich jak Martin, Fowler, Feathers, Beck, Cohn, etc, i ich książki takie jak Clean Code, Clean Architecture, Working Effectively with Legacy Code, etc. Im bliżej jesteśmy zaleceń zawartych w tych książkach, tym bardziej OOP jest nasz kod.

Wydaje mi się, że taka definicja byłaby dostatecznie blisko tego, co większość ludzi intuicyjnie rozumie przez OOP.

WeiXiao
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5227
0

@YetAnohterone

czemu akurat ich? to jakiś contest influencerów i ewangelistów? :D

YA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 252
1
WeiXiao napisał(a):

@YetAnohterone

czemu akurat ich? to jakiś contest influencerów i ewangelistów? :D

Bo wydaje mi się, że ludzie zazwyczaj własnie od nich czerpią pomysły, jak powinien wyglądać kod OOP. Z kolei pomysły inne niż te przedstawiane przez przeze mnie wymienionych influencerów zazwyczaj nie są uważane za OOP. Na przykład clean architecture jest powszechnie uważany za OOP, podczas gdy konkurencyjny vertical slice już raczej nie jest uważany za OOP i raczej jest po części na fali oporu przeciwko OOP.

Zresztą influencerzy przeze mnie wymienieni chyba stworzyli wspólnie dość spójną 'szkołę' programowania, swego czasu cytowali się wzajemnie dość sporo.

Again nie chodziło mi o definicję, która z jakiegoś teoretycznego, purystycznego punktu widzenia byłaby najsensowniejsza. Ile raczej o to, jak można w maks kilku zdaniach streścić, co wydaje mi się, że ludzie zazwyczaj za OOP uważają. A wydaje mi się, że ludzie za OOP uważają to, co jest w tamtych książkach.

DH
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 32
0
YetAnohterone napisał(a):

Zresztą influencerzy przeze mnie wymienieni chyba stworzyli wspólnie dość spójną 'szkołę' programowania, swego czasu cytowali się wzajemnie dość sporo.

Usilowalem sluchac / ogladac krajowych influencerow branzowych. Jedni uzywaja takiego jezyka ktorego nie da sie zwyczajnie sluchac. Drudzy robia z siebie guru po to aby sprzedawac szkolenia dla ulicy czy chodzic po firmach i mowic z wiezy jak rozwiazac rozne problemy bez wnikania w detale ktore badz co badz maja spore znaczenie.

Satanistyczny Awatar
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 750
0

OOP jest jak im pasuje. Jak im nie pasuje to wtedy nie jest OOP.

GO
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 358
0

Ciekawe, ja namiętnie czytam assemblera i obiekty są takie same jak struktury niczym się nie różnią, dla mnie obiekty to zwykłe miejsce w pamięci gdzie przechowujemy jakieś zmienne i tak jest rzeczywiście nie wiem czemu ludzie nie lubią OOP pewnie nie rozumieją assemblera...
Edit: proszę się nie czepiać, że nie wiem czym jest OOP :>

DE
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5
0

Obiektowa wersja programu w Ruby, czyż nie wygląda pięknie i czytelnie?

Kopiuj
class Game
  CHOICES = ["kamień", "papier", "nożyczki"]

  def initialize
    @user_score = 0
    @computer_score = 0
  end

  def play
    loop do
      user_choice = get_user_choice
      computer_choice = get_computer_choice
      puts "Twój wybór: #{user_choice}"
      puts "Wybór komputera: #{computer_choice}"
      result = determine_winner(user_choice, computer_choice)
      puts result
      update_scores(result)
      display_scores
      break unless play_again?
    end
  end

  private

  def get_user_choice
    puts "Wybierz: kamień, papier, nożyczki"
    choice = gets.chomp.downcase
    until CHOICES.include?(choice)
      puts "Nieprawidłowy wybór. Wybierz: kamień, papier, nożyczki"
      choice = gets.chomp.downcase
    end
    choice
  end

  def get_computer_choice
    CHOICES.sample
  end

  def determine_winner(user_choice, computer_choice)
    if user_choice == computer_choice
      "Remis!"
    elsif (user_choice == "kamień" && computer_choice == "nożyczki") ||
          (user_choice == "papier" && computer_choice == "kamień") ||
          (user_choice == "nożyczki" && computer_choice == "papier")
      "Wygrałeś!"
    else
      "Przegrałeś!"
    end
  end

  def update_scores(result)
    case result
    when "Wygrałeś!"
      @user_score += 1
    when "Przegrałeś!"
      @computer_score += 1
    end
  end

  def display_scores
    puts "Wynik: Ty - #{@user_score}, Komputer - #{@computer_score}"
  end

  def play_again?
    puts "Czy chcesz zagrać ponownie? (tak/nie)"
    answer = gets.chomp.downcase
    answer == "tak"
  end
end

game = Game.new
game.play

Obiektowość w Swift też dobrze wygląda.

Kopiuj
import Foundation

class Game {
    let choices = ["kamień", "papier", "nożyczki"]
    var userScore = 0
    var computerScore = 0

    func play() {
        while true {
            let userChoice = getUserChoice()
            let computerChoice = getComputerChoice()
            print("Twój wybór: \(userChoice)")
            print("Wybór komputera: \(computerChoice)")
            let result = determineWinner(userChoice: userChoice, computerChoice: computerChoice)
            print(result)
            updateScores(result: result)
            displayScores()
            if !playAgain() {
                break
            }
        }
    }

    private func getUserChoice() -> String {
        var choice: String?
        repeat {
            print("Wybierz: kamień, papier, nożyczki")
            choice = readLine()?.lowercased()
        } while choice == nil || !choices.contains(choice!)
        return choice!
    }

    private func getComputerChoice() -> String {
        return choices.randomElement()!
    }

    private func determineWinner(userChoice: String, computerChoice: String) -> String {
        if userChoice == computerChoice {
            return "Remis!"
        } else if (userChoice == "kamień" && computerChoice == "nożyczki") ||
                  (userChoice == "papier" && computerChoice == "kamień") ||
                  (userChoice == "nożyczki" && computerChoice == "papier") {
            return "Wygrałeś!"
        } else {
            return "Przegrałeś!"
        }
    }

    private func updateScores(result: String) {
        switch result {
        case "Wygrałeś!":
            userScore += 1
        case "Przegrałeś!":
            computerScore += 1
        default:
            break
        }
    }

    private func displayScores() {
        print("Wynik: Ty - \(userScore), Komputer - \(computerScore)")
    }

    private func playAgain() -> Bool {
        print("Czy chcesz zagrać ponownie? (tak/nie)")
        let answer = readLine()?.lowercased()
        return answer == "tak"
    }
}

let game = Game()
game.play()

Teraz porównanie wersji funkcyjnej Rust

Kopiuj
use std::io;

fn main() {
    let mut user_score = 0;
    let mut computer_score = 0;

    loop {
        let user_choice = get_user_choice();
        let computer_choice = get_computer_choice();
        println!("Twój wybór: {}", user_choice);
        println!("Wybór komputera: {}", computer_choice);

        match determine_winner(&user_choice, &computer_choice) {
            Outcome::UserWins => {
                println!("Wygrałeś!");
                user_score += 1;
            }
            Outcome::ComputerWins => {
                println!("Przegrałeś!");
                computer_score += 1;
            }
            Outcome::Draw => {
                println!("Remis!");
            }
        }

        display_scores(user_score, computer_score);

        if !play_again() {
            break;
        }
    }
}

fn get_user_choice() -> String {
    loop {
        println!("Wybierz: kamień, papier, nożyczki");
        let mut choice = String::new();
        io::stdin().read_line(&mut choice).expect("Nie udało się odczytać wyboru");
        let choice = choice.trim().to_lowercase();

        if ["kamień", "papier", "nożyczki"].contains(&choice.as_str()) {
            return choice;
        } else {
            println!("Nieprawidłowy wybór. Spróbuj ponownie.");
        }
    }
}

fn get_computer_choice() -> &'static str {
    let choices = ["kamień", "papier", "nożyczki"];
    let random_index = rand::random::<usize>() % choices.len();
    choices[random_index]
}

fn determine_winner(user_choice: &str, computer_choice: &str) -> Outcome {
    if user_choice == computer_choice {
        Outcome::Draw
    } else if (user_choice == "kamień" && computer_choice == "nożyczki") ||
              (user_choice == "papier" && computer_choice == "kamień") ||
              (user_choice == "nożyczki" && computer_choice == "papier") {
        Outcome::UserWins
    } else {
        Outcome::ComputerWins
    }
}

fn display_scores(user_score: u32, computer_score: u32) {
    println!("Wynik: Ty - {}, Komputer - {}", user_score, computer_score);
}

fn play_again() -> bool {
    println!("Czy chcesz zagrać ponownie? (tak/nie)");
    let mut answer = String::new();
    io::stdin().read_line(&mut answer).expect("Nie udało się odczytać odpowiedzi");
    answer.trim().to_lowercase() == "tak"
}

enum Outcome {
    UserWins,
    ComputerWins,
    Draw,
}

DE
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5
0

Czy taki program w językach funkcyjnych jak Haskell, Scala, Elixir jest lepszy, składnia jest bardziej czytelna lepiej to wygląda?

Kopiuj
import System.Random (randomRIO)
import Control.Monad (when)

data Choice = Rock | Paper | Scissors deriving (Show, Eq)

main :: IO ()
main = do
    putStrLn "Witaj w grze w Papier, Kamień, Nożyczki!"
    playGame 0 0

playGame :: Int -> Int -> IO ()
playGame userScore computerScore = do
    userChoice <- getUserChoice
    computerChoice <- getComputerChoice
    putStrLn $ "Twój wybór: " ++ show userChoice
    putStrLn $ "Wybór komputera: " ++ show computerChoice
    let result = determineWinner userChoice computerChoice
    putStrLn result
    let (newUserScore, newComputerScore) = updateScores result userScore computerScore
    putStrLn $ "Wynik: Ty - " ++ show newUserScore ++ ", Komputer - " ++ show newComputerScore
    playAgain newUserScore newComputerScore

getUserChoice :: IO Choice
getUserChoice = do
    putStrLn "Wybierz: kamień, papier, nożyczki"
    choice <- getLine
    case choice of
        "kamień" -> return Rock
        "papier" -> return Paper
        "nożyczki" -> return Scissors
        _ -> do
            putStrLn "Nieprawidłowy wybór. Spróbuj ponownie."
            getUserChoice

getComputerChoice :: IO Choice
getComputerChoice = do
    randomIndex <- randomRIO (0, 2) :: IO Int
    return $ case randomIndex of
        0 -> Rock
        1 -> Paper
        2 -> Scissors

determineWinner :: Choice -> Choice -> String
determineWinner user computer
    | user == computer = "Remis!"
    | (user == Rock && computer == Scissors) ||
      (user == Paper && computer == Rock) ||
      (user == Scissors && computer == Paper) = "Wygrałeś!"
    | otherwise = "Przegrałeś!"

updateScores :: String -> Int -> Int -> (Int, Int)
updateScores result userScore computerScore =
    case result of
        "Wygrałeś!" -> (userScore + 1, computerScore)
        "Przegrałeś!" -> (userScore, computerScore + 1)
        _ -> (userScore, computerScore)

playAgain :: Int -> Int -> IO ()
playAgain userScore computerScore = do
    putStrLn "Czy chcesz zagrać ponownie? (tak/nie)"
    answer <- getLine
    when (answer == "tak") $ playGame userScore computerScore

Scala 3

Kopiuj
import scala.io.StdIn
import scala.util.Random

enum Choice:
  case Rock, Paper, Scissors

object PaperRockScissors:
  def main(args: Array[String]): Unit =
    println("Witaj w grze w Papier, Kamień, Nożyczki!")
    playGame(0, 0)

  def playGame(userScore: Int, computerScore: Int): Unit =
    val userChoice = getUserChoice()
    val computerChoice = getComputerChoice()
    println(s"Twój wybór: $userChoice")
    println(s"Wybór komputera: $computerChoice")
    
    val result = determineWinner(userChoice, computerChoice)
    println(result)
    
    val (newUserScore, newComputerScore) = updateScores(result, userScore, computerScore)
    println(s"Wynik: Ty - $newUserScore, Komputer - $newComputerScore")
    
    if playAgain() then
      playGame(newUserScore, newComputerScore)

  def getUserChoice(): Choice =
    println("Wybierz: kamień, papier, nożyczki")
    StdIn.readLine().toLowerCase match
      case "kamień" => Choice.Rock
      case "papier" => Choice.Paper
      case "nożyczki" => Choice.Scissors
      case _ =>
        println("Nieprawidłowy wybór. Spróbuj ponownie.")
        getUserChoice()

  def getComputerChoice(): Choice =
    Random.nextInt(3) match
      case 0 => Choice.Rock
      case 1 => Choice.Paper
      case 2 => Choice.Scissors

  def determineWinner(user: Choice, computer: Choice): String =
    if user == computer then "Remis!"
    else (user, computer) match
      case (Choice.Rock, Choice.Scissors) => "Wygrałeś!"
      case (Choice.Paper, Choice.Rock) => "Wygrałeś!"
      case (Choice.Scissors, Choice.Paper) => "Wygrałeś!"
      case _ => "Przegrałeś!"

  def updateScores(result: String, userScore: Int, computerScore: Int): (Int, Int) =
    result match
      case "Wygrałeś!" => (userScore + 1, computerScore)
      case "Przegrałeś!" => (userScore, computerScore + 1)
      case _ => (userScore, computerScore)

  def playAgain(): Boolean =
    println("Czy chcesz zagrać ponownie? (tak/nie)")
    StdIn.readLine().toLowerCase == "tak"


Elixir funkcyjnie

Kopiuj
defmodule PaperRockScissors do
  @choices ["kamień", "papier", "nożyczki"]

  def start do
    IO.puts("Witaj w grze w Papier, Kamień, Nożyczki!")
    play_game(0, 0)
  end

  defp play_game(user_score, computer_score) do
    user_choice = get_user_choice()
    computer_choice = get_computer_choice()
    
    IO.puts("Twój wybór: #{user_choice}")
    IO.puts("Wybór komputera: #{computer_choice}")

    result = determine_winner(user_choice, computer_choice)
    IO.puts(result)

    {new_user_score, new_computer_score} = update_scores(result, user_score, computer_score)
    IO.puts("Wynik: Ty - #{new_user_score}, Komputer - #{new_computer_score}")

    if play_again() do
      play_game(new_user_score, new_computer_score)
    end
  end

  defp get_user_choice do
    IO.puts("Wybierz: kamień, papier, nożyczki")
    choice = String.trim(IO.gets("> ")) |> String.downcase()

    if choice in @choices do
      choice
    else
      IO.puts("Nieprawidłowy wybór. Spróbuj ponownie.")
      get_user_choice()
    end
  end

  defp get_computer_choice do
    Enum.random(@choices)
  end

  defp determine_winner(user, computer) do
    cond do
      user == computer -> "Remis!"
      (user == "kamień" && computer == "nożyczki") or
      (user == "papier" && computer == "kamień") or
      (user == "nożyczki" && computer == "papier") -> "Wygrałeś!"
      true -> "Przegrałeś!"
    end
  end

  defp update_scores(result, user_score, computer_score) do
    case result do
      "Wygrałeś!" -> {user_score + 1, computer_score}
      "Przegrałeś!" -> {user_score, computer_score + 1}
      _ -> {user_score, computer_score}
    end
  end

  defp play_again do
    IO.puts("Czy chcesz zagrać ponownie? (tak/nie)")
    answer = String.trim(IO.gets("> ")) |> String.downcase()
    answer == "tak"
  end
end

PaperRockScissors.start()

LU
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 7
0

Ciekawe dlaczego zawsze do nauki obiektowości polecają Javę. Jest tyle lepszych języków obiektowych jak Dart, C#, Ruby, TS, obiektowość w tych językach nie jest tak zagmatwana jak w Javie. Obiektowość w Javie jest tak zawiła i rozwlekła że często idzie się w tym zagubić. Może trzeba szukać nowych lepszych alternatyw do OOP jak język Lucee na JVM?
https://www.lucee.org/

ToTomki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1365
0
Lucee napisał(a):

Ciekawe dlaczego zawsze do nauki obiektowości polecają Javę. Jest tyle lepszych języków obiektowych jak Dart, C#, Ruby, TS, obiektowość w tych językach nie jest tak zagmatwana jak w Javie

W Javie masz pierdyliard projektów do utrzymania. W Darcie 2, w Rubym 3, a C# uczy się podobnie jak Javy

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.