Решение на Девета задача от Мартина Тонковска

Обратно към всички решения

Към профила на Мартина Тонковска

Резултати

  • 6 точки от тестове
  • 0 бонус точки
  • 6 точки общо
  • 1 успешни тест(а)
  • 0 неуспешни тест(а)

Код

REPOSITORY = 'https://github.com/misosupu/ruby-retrospective-2015-1'
# Какво научих от Ruby Retrospective, част 1:
#
# 1. Хешовете в ruby имат "опростен" запис при работа с ключове, които са от тип symbol
# вместо да се напише така:
# EXCHANGE_RATE = { :usd => 1.7408, :eur => 1.9557, :gbp => 2.6415, :bgn => 1 }
# можем да напишем следното:
# EXCHANGE_RATE = { usd: 1.7408, eur: 1.9557, gbp: 2.6415, bgn: 1 }
#
# 2. Насърчаване на използване на символи спрямо низове като ключове на хеш
#
# Взето от "Ruby Style guide": "Prefer symbols instead of strings as hash keys."
#
# 3. На какъв принцип работи spaceship operator-ът при сравняване на обекти:
# a <=> b връща -1 ако a е преди b,
# 0 ако са равни
# или 1 ако a е след b
#
# 4. типове променливи в Ruby и конвенцията за именоването им:
# $variable = константа
# Variable = глобална (за namespace-a) променлива
#
# * Bonus: да не предполагам, че през първата седмица от семестъра няма да се дават домашни
#
# 5. Няма смисъл от допълнителни операции, документацията съществува, за да се чете, например:
# new_snake.shift
# new_snake
#
# може да се замени просто със snake.drop(1)
#
# 6. [Концептуално] Хубаво е смислово различните случаи да се разделят в отделни методи, по този начин се улеснява тестването (TDD), кодът става по-четим и рефакторирането - по-лесно.
#
# Например за функцията obstacle_ahead? очевидно имаме 2 случая:
# 1) змията пресича "себе си"
# или
# 2) змията пресича "границата"
#
# Разделяйки тези 2 случая в отделни методи е подобрение, освен по горепосочените причини, а и че намалява branching factor-a на метода. Добре е методите да правят точно това, което е името им, а не хиляда други неща. Грозно и нефункционално е.
#
# 7. Премахване на безсмиленото усложняване на код
# x.zip(y).reduce(:+) е overkill
# Освен, че е по-бавно, прави кода ненужно по-сложен и трудно читаем.
#
# По-краткото невинаги е най-доброто - "Programs were made for people to read and occasionally for machines to execute."
#
# 8. Отново, от Ruby Style guide-а:
# "The and and or keywords are banned. It's just not worth it. Always use && and || instead."
# Навсякъде съм заменила използването на 'and' и 'or' с '&&' и '||'.
#
# 9. Разлика между използването на ".." и "..." при задаване на range:
# a..b is like a <= x <= b, whereas a...b is like a <= x < b
#
# 10. "Prefer Guard Clauses over nested conditionals"
# Например:
# if number == 1 || number == 2
# return true
# end
#
# може да се запише и така:
# return true if number == 1 || number == 2
#
# 11. Използването на "upto" вместо range понякога подобрява четимостта и прави кода по-елегантен, отколкото използването на range.
#
# 12. Разликата между Struct и OpenStruct e, че с OpenStruct може динамично да се задават атрибути на даден обект, докато при Struct всички атрибути се задават при дефинирането.
#
# [Концептуално] Използването на Struct подобрява четимостта на кода.
#
# 13. [Концептуално]
#
# Преименуване на всички методи, съдържащи is_something? на something?. Въпросителната накрая говори достатъчно красноречиво за целта на метода.
#
# 14. Използване на unless, вместо if not.
#
# 15. Няма смисъл от отделен клас RationalSequenceElement с функционалност само един метод - всичко това може да стане със Struct и private method
#
# 16. Извикване на методи със символи, например cards.select(&:queen?) вместо card.select {|card| card.queen?}
# Този начин е по-чист, елегантен и четим.
#
# 17. [Концептуално] Хубаво е да се групират общите функционалности на няколко класа и или да има основен, който да се наследява (например WarDeck < GenerickDeck) или общите методи да се групират в отделен модул, които да се mixin-не в съответните класове.
#
# 18. Съкратен начин на Array#push е операторът '<<'
#
# Например, вместо [1, 2, 3].push(4) # => [1, 2, 3, 4]
# можем да напишем [1, 2, 3] << 4
#
# 19. Доста от методите в Ruby имат синоними (например size, length и.т.н.), но има методи, при които използването на един от синонимите е силно непрепоръчително, поради неудачно/смущаващо име.
#
# Например Enumerable#reduce и Enumerable#inject.
#
# 20. Тъй като в Ruby всеки метод по default връща последно оценения израз, добра идея е да избягваме множество return-и в средата на метода, тъй като обезсмислят първоначалната идея. Функциите стават по-четими и се намалява вероятността за по-голям branching factor, ако избягваме прекаленото използване на return клаузи.
#
# Bonus:
# 1. Научих, че Rational е синтактична захар за named tuple.
# 2. Ruby не е Python - имената на методи не започват с underscore, нито с dunder - използват се *something* private, public, protected.

Лог от изпълнението

From https://github.com/fmi/ruby-retrospective-2015-1
 * branch            master     -> FETCH_HEAD
HEAD is now at 767dd8d Update the task name in the readme for clarity
Cloning into 'submission'...
HEAD is now at 728bfb7 Improved solutions
From /tmp/ruby-retrospective-2015-1/checker
 * branch            master     -> FETCH_HEAD
 * [new branch]      master     -> upstream/master

Changes URL:
https://github.com/misosupu/ruby-retrospective-2015-1/compare/767dd8dfe46...728bfb72ae2

‘solutions/04.rb’ -> ‘/tmp/ruby-retrospective-2015-1/checker/solutions/04.rb’
‘solutions/02.rb’ -> ‘/tmp/ruby-retrospective-2015-1/checker/solutions/02.rb’
‘solutions/03.rb’ -> ‘/tmp/ruby-retrospective-2015-1/checker/solutions/03.rb’
‘solutions/01.rb’ -> ‘/tmp/ruby-retrospective-2015-1/checker/solutions/01.rb’
OK
........

Finished in 0.00487 seconds
8 examples, 0 failures
OK
....................

Finished in 0.0111 seconds
20 examples, 0 failures
OK
....................

Finished in 0.13445 seconds
20 examples, 0 failures
OK
.........................................................

Finished in 0.02687 seconds
57 examples, 0 failures
From https://github.com/fmi/ruby-homework
 * branch            master     -> FETCH_HEAD
HEAD is now at 9dd040c Modify a test in task 8 to not include empty cells
.

Finished in 0.00159 seconds
1 example, 0 failures

История (1 версия и 1 коментар)

Мартина обнови решението на 25.01.2016 01:19 (преди над 9 години)

+REPOSITORY = 'https://github.com/misosupu/ruby-retrospective-2015-1'
+
+# Какво научих от Ruby Retrospective, част 1:
+#
+# 1. Хешовете в ruby имат "опростен" запис при работа с ключове, които са от тип symbol
+# вместо да се напише така:
+# EXCHANGE_RATE = { :usd => 1.7408, :eur => 1.9557, :gbp => 2.6415, :bgn => 1 }
+# можем да напишем следното:
+# EXCHANGE_RATE = { usd: 1.7408, eur: 1.9557, gbp: 2.6415, bgn: 1 }
+#
+# 2. Насърчаване на използване на символи спрямо низове като ключове на хеш
+#
+# Взето от "Ruby Style guide": "Prefer symbols instead of strings as hash keys."
+#
+# 3. На какъв принцип работи spaceship operator-ът при сравняване на обекти:
+# a <=> b връща -1 ако a е преди b,
+# 0 ако са равни
+# или 1 ако a е след b
+#
+# 4. типове променливи в Ruby и конвенцията за именоването им:
+# $variable = константа
+# Variable = глобална (за namespace-a) променлива
+#
+# * Bonus: да не предполагам, че през първата седмица от семестъра няма да се дават домашни
+#
+# 5. Няма смисъл от допълнителни операции, документацията съществува, за да се чете, например:
+# new_snake.shift
+# new_snake
+#
+# може да се замени просто със snake.drop(1)
+#
+# 6. [Концептуално] Хубаво е смислово различните случаи да се разделят в отделни методи, по този начин се улеснява тестването (TDD), кодът става по-четим и рефакторирането - по-лесно.
+#
+# Например за функцията obstacle_ahead? очевидно имаме 2 случая:
+# 1) змията пресича "себе си"
+# или
+# 2) змията пресича "границата"
+#
+# Разделяйки тези 2 случая в отделни методи е подобрение, освен по горепосочените причини, а и че намалява branching factor-a на метода. Добре е методите да правят точно това, което е името им, а не хиляда други неща. Грозно и нефункционално е.
+#
+# 7. Премахване на безсмиленото усложняване на код
+# x.zip(y).reduce(:+) е overkill
+# Освен, че е по-бавно, прави кода ненужно по-сложен и трудно читаем.
+#
+# По-краткото невинаги е най-доброто - "Programs were made for people to read and occasionally for machines to execute."
+#
+# 8. Отново, от Ruby Style guide-а:
+# "The and and or keywords are banned. It's just not worth it. Always use && and || instead."
+# Навсякъде съм заменила използването на 'and' и 'or' с '&&' и '||'.
+#
+# 9. Разлика между използването на ".." и "..." при задаване на range:
+# a..b is like a <= x <= b, whereas a...b is like a <= x < b
+#
+# 10. "Prefer Guard Clauses over nested conditionals"
+# Например:
+# if number == 1 || number == 2
+# return true
+# end
+#
+# може да се запише и така:
+# return true if number == 1 || number == 2
+#
+# 11. Използването на "upto" вместо range понякога подобрява четимостта и прави кода по-елегантен, отколкото използването на range.
+#
+# 12. Разликата между Struct и OpenStruct e, че с OpenStruct може динамично да се задават атрибути на даден обект, докато при Struct всички атрибути се задават при дефинирането.
+#
+# [Концептуално] Използването на Struct подобрява четимостта на кода.
+#
+# 13. [Концептуално]
+#
+# Преименуване на всички методи, съдържащи is_something? на something?. Въпросителната накрая говори достатъчно красноречиво за целта на метода.
+#
+# 14. Използване на unless, вместо if not.
+#
+# 15. Няма смисъл от отделен клас RationalSequenceElement с функционалност само един метод - всичко това може да стане със Struct и private method
+#
+# 16. Извикване на методи със символи, например cards.select(&:queen?) вместо card.select {|card| card.queen?}
+# Този начин е по-чист, елегантен и четим.
+#
+# 17. [Концептуално] Хубаво е да се групират общите функционалности на няколко класа и или да има основен, който да се наследява (например WarDeck < GenerickDeck) или общите методи да се групират в отделен модул, които да се mixin-не в съответните класове.
+#
+# 18. Съкратен начин на Array#push е операторът '<<'
+#
+# Например, вместо [1, 2, 3].push(4) # => [1, 2, 3, 4]
+# можем да напишем [1, 2, 3] << 4
+#
+# 19. Доста от методите в Ruby имат синоними (например size, length и.т.н.), но има методи, при които използването на един от синонимите е силно непрепоръчително, поради неудачно/смущаващо име.
+#
+# Например Enumerable#reduce и Enumerable#inject.
+#
+# 20. Тъй като в Ruby всеки метод по default връща последно оценения израз, добра идея е да избягваме множество return-и в средата на метода, тъй като обезсмислят първоначалната идея. Функциите стават по-четими и се намалява вероятността за по-голям branching factor, ако избягваме прекаленото използване на return клаузи.
+#
+# Bonus:
+# 1. Научих, че Rational е синтактична захар за named tuple.
+# 2. Ruby не е Python - имената на методи не започват с underscore, нито с dunder - използват се *something* private, public, protected.

Не бих казал, че inject е точно смущаващо име. Не е довело до основаването на наркомански култ or something. xd

Причините reduce да се предпочита IMHO:

  • По-ясно е. Да, във функционален контекст inject също може да значи само едно нещо, но все пак reduce е по-недвусмислено. По същия начин е по-добре и от accumulate.
  • По-разпространен е в developer culture-a като цяло. Хората говорят за MapReduce, не за MapInject.
  • Преди each_with_object е имало хора, които са използвали reduce за "идиоматичен reduce" и inject за това, за което each_with_object е предназначен. Сега като вече го има...