The usual way in which we plan today for tomorrow is in yesterday’s vocabulary. We do so, because we try to get away with the concepts we are familiar with and that have acquired their meanings in our past experience. Of course, the words and the concepts don’t quite fit because our future differs from our past, but then we stretch them a little bit.
On the cruelty of really teaching computer science
Terminy prezentacji projektów:
-
stacjonarne: 16, 23 stycznia 2018, g. 16:00, aula 1.
-
niestacjonarne: 21, 28 stycznia 2018.
Wydrukowaną dokumentację projektu należy oddać do 15.01.2018. Dokumentacja dostarczona po 22.01.2018 – ocena obniżona. Niedostarczenie dokumentacji do 22.01.2018 – ocena ndst w pierwszym terminie.
Ostateczne oceny z egzaminu zostaną ustalone z każdym z zespołów 29.01.2018, w godz 11:00-12:00 (stacjonarne) 28.01.2018 po zajęciach (niestacjonarne).
Przypominam, że warunkiem przystąpienia do egzaminu jest podłączenie repozytorium z projektem do GitHub Classroom. Invitation Link dostępny jest u prowadzących.
Więcej szczegółów dotyczących projektu Open/Closed opisano w pliku egzamin_template.adoc.
Egzamin poprawkowy z teorii będzie miał formę pisemną. Dokładny termin egzaminu podam później.
If your application succeeds many of the decisions you make today will need to be changed later. […] Design is more the art of preserving changeability than it is the act of achieving perfection.
Practical Object Oriented Design in Ruby
Literatura
-
Greg Young, The art of destroying software (Vimeo)
-
Refactoring Ruby Edition by Jay Fields, Shane Harvie, and Martin Fowler (with Kent Beck), Java Edition by Martin Fowler (with Kent Beck, John Brant, William Opdyke, and Don Roberts)
-
Gerard Meszaros, xUnit Test Patterns Refactoring Test Code, Addison Wesley (2007), Code Refactorings
-
Czysty kod. Podręcznik dobrego programisty and The Future of Programming (YouTube) by Robert C. Martin (Uncle Bob),
-
Practical Object-Oriented Design in Ruby – a programmers tale about how to write object-oriented code by Sandi Metz or 99 Bottles off OOP – a practical guide to writing cost-effective, maintainable, and pleasing object-oriented code by Sandi Metz & Katrina Owen
-
On the cruelty of really teaching computer science by Edsger W. Dijkstra
Narzędzia
-
Learn Enough by Michael Hartl
-
Git
-
Pro Git book by Scott Chacon and Ben Straub
-
-
Linters
-
Code smell detectors (and brothers & sisters)
-
Editors
The foundation of an object-oriented system is the message, but the most visible organizational structure in a a class-based OO language (Ruby) is the class.
So, how to create classes to allow for easy changes?
You will never know less than you know right now.
RED |
Write a new test and see it fail. |
GREEN |
Get all tests passing, using the most naive approach you can see. |
REFACTOR |
Transition to the simplest design that passes the current tests, by removing any introduced smells. |
repeat |
- Programmer State Attention Exclusion Principle
-
A programmer attentions should not occupy different states simultaneously.
Refactoring to proces/metoda bezpiecznego udoskonalania istniejącego kodu. Innymi słowami, w trakcie refactoringu poprawiamy kod udoskonalając jego wewnętrzną strukturę i nie zmieniając jego działania (semantyki, behavior).
W książce Refactoring – RubyEdition opisano ok. 80 refactoringów.
W trakcie refactoringu zmienia się nasze rozumienie cudzego kodu Dlatego kod po refactoringu jest łatwiejszy w zrozumieniu i łatwiej go rozszerzać (szybciej piszemy nowy kod i robimy mniej błędów).
Refactorings are designed to be safe transformations. But mistakes happens. So, use Git.
class Rectangle
attr_reader :top_left, :width, :height
def initialize top_left, width, height
@top_left = top_left
@width = width
@height = height
end
end
class Point
attr_reader :x, :y
def initialize x, y
@x = x
@y = y
end
end
To find the x-coordinate of a rectangle’s left coordinate we have to use:
rect = Rectangle.new Point.new(4, 5), 3, 2
left_x = rect.top_left.x
and we may want to hide this delegation.
The suggested steps for Hide Delegate are following:
-
Create a delegating method on the
Rectangle
class. Test. -
For each client of the delegate adjust it to call the new method. Test.
-
If no client needs to access the delegate any longer remove the
Rectangle
accessor for the delegate. Test.
class Rectangle
def left_edge
@top_left.x
end
end
left_x = rect.left_edge
class Rectangle
attr_reader :width, :height
end
Code smells suggest refactorings.
A code smell is a surface indication that usually corresponds to a deeper problem in the system. The term was first coined by Kent Beck while helping me with my Refactoring book.
CodeSmell
🎶
|
Move Method, Extract Class, Move Field, Extract Method: probably, these refactorings are responsible for fixing the most smells. |
|
Quite a few refactorings are not mentioned by any of the smells. |
- Lista wszystkich code smells z książki Refactoring – Edition by Jay Fields et al.
-
Duplicated Code (zduplikowany kod), Long Method (długa metoda), Large Class (duża klasa), Long Parameter List (długa lista parametrów), Divergent Change (rozbieżne zmiany), Shotgun Surgery (fala uderzeniowa), Feature Envy (zazdrosne metody), Data Clumps (stada danych), Primitive Obsession / Open Secret (opętanie prymitywami), Case Statement (instrukcja case), Parallel Inheritance Hierarchies (równoległe hierarchie dziedziczenia), Lazy Class (leniwa klasa), Speculative Generality (spekulacyjne uogólnienia), Temporary Field (pole tymczasowe), Message Chains (łańcuchy komunikatów), Middle Man (pośrednik), Inappriopriate Intimacy (niestosowna bliskość), Alternative Classes with Different Interfaces (alternatywne klasy z różnymi interfejsami), Incomplete Library Class (niekompletna klasa biblioteczna), Data Class (klasa danych), Refused Bequest (odmowa przyjęcia spadku), Comments (komentarze), Metaprogramming Madness (szaleństwo metaprogramowania), Disjointed API (rozłączne API), Repetitive Boilerplate (powtarzający się szablon).
-
Jeff Atwood, Code Smells – develop your „code nose” by watching for warning signs in your own code.
-
Smells ➨ Refactorings cheatsheet (source)
-
start with working (tested) code while the design can be simplified choose the worst smell select a refactoring that will address the smell apply the refactoring (check that tests still pass)
✅
|
This approach to refactoring does not guarantee to get the ideal design, because you can not reach a global maximum by looking at local properties. |
|
|
💡
|
|
Przykład automatycznego wyszukiwania code smells w pliku za pomocą programu reek – Code smell detector for Ruby.
# Smelly class
class Smelly
# This will reek of UncommunicativeMethodName
def x
y = 10 # This will reek of UncommunicativeVariableName
end
end
reek smelly.rb
Inspecting 1 file(s):
S
smelly.rb -- 2 warnings:
[4]:UncommunicativeMethodName: Smelly#x has the name 'x' [https://github.com/troessner/reek/blob/master/docs/Uncommunicative-Method-Name.md]
[5]:UncommunicativeVariableName: Smelly#x has the variable name 'y' [https://github.com/troessner/reek/blob/master/docs/Uncommunicative-Variable-Name.md]
Do wyszukiwania pain in code możemy użyć narzędzia flog – the higher the score, the more pain the code is in. Przykład jest na stronie Flog.
def verse(n)
"#{n == 0 ? 'No more' : n} bottle#{'s' if n != 1}" +
" of beer on the wall, " +
"#{n == 0 ? 'no more' : n} bottle#{'s' if n != 1} of beer.\n" +
"#{n > 0 ? "Take #{n > 1 ? 'one' : 'it'} down and pass it around"
: "Go to the store and buy some more"}, " +
"#{n-1 < 0 ? 99 : n-1 == 0 ? 'no more' : n-1} bottle#{'s' if n-1 != 1}"+
" of beer on the wall.\n"
end
flog -ad verse.rb # --all --details
36.2: flog total
36.2: flog/method average
36.2: main#verse verse.rb:1-8
15.2: branch
7.0: +
6.5: -
5.3: ==
5.2: !=
4.1: lit_fixnum
3.3: >
1.4: <
Aby oszacować liczbę "zapachów" danego typu w projekcie można posłużyć się komendą:
reek -f json KATALOG | jq .[].wiki_link -r | sort | uniq -c | sort -n
Przykład:
reek -f json lib | jq .[].wiki_link -r | sort | uniq -c | sort -n
Więcej przykładowych programów do wybróbowania z programem reek można znależć na Learn Ruby (Beginner, Intermediate, Advanced, TDD).
Można też spróbować swoich sił na zadaniach z portalu Exercism.
exercism list ruby
exercism fetch ruby beer-song
Checkout by date:
git rev-list -1 --before=2015-10-6 master | xargs git checkout
Compare:
git diff tag_1 tag_2
git diff tag1 tag2 --stat # list of files
git diff tag1 tag2 -- some/file/name # look at differences for some file
git diff --name-status master..branch_or_tag_name
git diff master..branch_or_tag_name
-
Oh shit, git! – Git is hard: screwing up is easy, and figuring out how to fix your mistakes is fucking impossible.