Mam pytanie czy w języku Ruby zawsze starać się używać klas?
Napisałem właśnie skrypt do obliczenia wyrażenia x/(x2-4) dla x >0;
#!/usr/bin/env ruby
require 'mathn'
puts "podaj liczbe"
x = gets.to_i
if x>0 then
y = x/(x**2 - 4)
puts y
else
puts "Podałeś złą liczbę"
end
I teraz moje pytanie czy dla tak prostego skryptu poprawniej byłoby użyć klasy?
Jeżeli tak to jak powinna wyglądać? Czy może mi ktoś wytłumaczyć jak poprawnie skonstruwać klasę i metody? Bo starałęm się napisać klase, która miałaby obliczać wyrażenie x/(x^2-4) jednak wychodziły mi same błędy a bez klasy bez problemu napisałem i działa
Ale gdyby skrypt był częścią większego systemu i chciałbyś dodatkowo napisać testy to bardziej abstrakcyjna wersja mogłaby wyglądać tak:
#calculator.rb
require 'mathn'
class Calculator
def run
@value = get_value
if valid?
render_response(calculate)
else
render_error
end
end
private
def calculate
@value / (@value ** 2 - 4)
end
def valid?
@value > 0
end
def get_value
prompt
gets.to_s.chomp.to_i
end
def prompt
puts 'podaj liczbę'
end
def render_response(v)
puts v
end
def render_error
puts 'Podałeś złą liczbę'
end
end
#main.rb
require_relative 'calculator'
c = Calculator.new
c.run
Dziękuję za szybkie odpowiedzi. Mam tylko pytanie, co oznacza słowo private w skrypcie Arthwood’a i po co zostało użyte? Jakie jest jego zadanie skoro skrypt się wykonał mi gdy je pominąłem?
Nie wiem też dlaczego skrypt nie działa gdy jest require_relative ‘calculator’ gdy skasowałem to wyrażanie, skrypt się uruchomił. Wcześniej dostałe komunikat Cannot load such file … calculator.
Czy że powinienem pierwszą część skryptu z klasą zapisać gdzieś w pliku a w drugim gdy wpisze wyrażenie require_relative ‘calculator’ to odnosi się do klasy? Jeśli tak to gdzie powinienem zapisać plik z klasą Calculator?
private oznacza że metody są ukryte i nie można użyć ich jako calculator.get_value. Zawsze staraj się ukrywać jak najwięcej
plik main.rb i calculator.rb w tym przypadku powinny być “obok siebie”. Dzięki takiemu rozseparowaniu masz podział na definicję i użycie.
@edit (bo jest tu jakieś dziwne ograniczenie do 3 postów per wątek dla nowych użytkowników)
@wafcio Te dwie strony o których piszesz się nie wykluczają. Metody prywatne powinny być trywialne i należy ukrywać jak najwięcej.
@Arnvald Zawsze się znajdzie jakaś przeciwwaga ale tu nie chodzi o to że są złe jako takie, tylko domyślam się że często wpycha się do prywatnych metod rzeczy które powinny być w osobnych klasach.
@mark Przesadzasz przykład miał pokazać jak z tego kodu zrobić klasę a nie jak napisać koszerny projekt Można przyjąć że ta klasa stanowi kalkulator jako całość razem z przyciskami i wyświetlaczem a nie jako procedurę obliczeniową.
Nie do końca się z tym zgodze, ukrywać powinno się z jednej strony jak najwięcej metod, ale z drugiej strony metody private powinny być na tyle trywialne żeby nie wymagały testów (jednostkowych), bo nie zaleca się pisania testów jednostkowych do private.
@arthwood, @Arnvald każda moneta ma dwie strony, kiedyś wymyślono ActiveRecord i wszyscy byli happy że można tam wszystko umieszczać, a teraz idzie się w kierunku tego, żeby klasy posiadały jak najmniej logiki i rozbija się duże klasy na wiele mniejszych. Więc potrzebny jest punkt wyważenia.
Klasa Calculator ma inna zasadnicza wade - robi zbyt duzo. Czyli:
pobiera wartosc z konsoli
wylicza wynik
a powinna robic tylko to 2gie. Wtedy mozna jej uzyc do wykonania tego skomplikowanego obliczenia bez wzgledu na to skad wezma sie dane wejsciowe. Chyba ze przyjac ze jest to program unixowy ktory standardowo czyta dane ze standardowego wejscia. Ale wtedy takim ‘programem’ i tak powinien byc jakis calculator.rb ktory wczytuje dane i uruchamia instancje Calculator. Chyba
Dzięki za wytłumaczenie. Teraz przynajmniej wiem co i jak.
Jutro spróbuje napisać własną klasę, która będzie tylko
obliczała wyrażenie, a reszta będzie poza klasą. I przedstawię wam do oceny.
Wiem, że po tych przykładach, które podaliście to już mam w zasadzie gotowca ale
przecież jedną z metod nauki jest czytanie kodu innych i modyfikowanie go
Na podstawie podanych przykładów napisałem jeszcze raz skrypt.
A tak wygląda moja modyfikacja.
#!/usr/bin/env ruby
class Calculator
def set_value(x)
@value = x
end
def calculate
@value / ( @value ** 2 - 4)
end
end
puts 'Podaj liczbę'
x = gets.to_s.chomp.to_f
if x > 0 then
c = Calculator.new
c.set_value(x)
print 'Dla podanej liczby wynik wynosi: '
puts c.calculate
else
puts 'Podałeś niepoprawną wartość.'
end
Czy tak napisany skrypt i wykorzystnie klasy jest poprawne? Wiem, że mój kod jest mało profesjonalny w porównaniu do waszych, ale chodzi mi czy zaliczylibyście tak rozwiązane zadanie?
I jeszcze pytanie czy dobrzez że użyłem typu zmiennopozycyjnego aby otrzymać także reszte przy dzieleniu a nie tylko samą liczbę całkjowitą z obcietą resztą?
Czy może użycie typu zmiennopozycyjnego powinno być użyte w ten sposób?
@value.to_f / ( @value.** to_f** ** 2 - 4)
x = gets.to_s.chomp.to_i
#!/usr/bin/env ruby
class Calculator
def set_value(x)
@value = x
end
def calculate
@value.to_f / ( @value.to_f ** 2 - 4)
end
end
puts 'Podaj liczbę'
x = gets.to_s.chomp.to_i
if x > 0 then
c = Calculator.new
c.set_value(x)
print 'Dla x wynik wynosi: '
puts c.calculate
else
puts 'Podałeś niepoprawną wartość.'
end
wcięcia dla pierwszej metody w klasie sa inne niz wciezia dla drugiej metody
Racja to przez mój pośpiech na przyszłość będę bardziej dokładny.
nie get_value tylko set_value bo to ustawia wartosc w zmiennej instancji
Na to nie mam usprawiedliwienia. Wstyd mi Bo wiecie jak to jest z początkującymi, bardziej myślą żeby coś zaprogramować i żeby działało niż dbać o poprawność kodu. Ale na przyszłość będę się starał nie popełniać takich błędów.
Mam jeszcze pytanie. Bo jeśli zastosuję tutaj typ zmiennopozycyjny: x = gets.to_s.chomp.to_f
a układ równań ma znajdować rozwiązanie dla x należącego do liczb rzeczywistych, to nie ma zabezpieczenia przed wpisanie liczby innej niż rzeczywista. W związku z tym czy można najpierw użyć
x = gets.to_s.chomp.to_i
a potem w metodzie calculate zrobić coś takiego @value.to_f / ( @value.to_f ** 2 - 4)
Czy taka praktyka byłaby poprawna? Czy jest na to inny bardziej poprawny sposób?