wermajew / ztp

OOD

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Zaawansowane Języki Programowania, 17/18

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.

— Edsger W. Dijkstra
On the cruelty of really teaching computer science

📝 Egzamin – prezentacje z projektu Open/Closed

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.

How to start „smelling” code?

How to start smelling code

From Simplicity to Changeability

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.

— S. Metz
Practical Object Oriented Design in Ruby

 

Literatura

  1. Greg Young, The art of destroying software (Vimeo)

  2. 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)

  3. Gerard Meszaros, xUnit Test Patterns Refactoring Test Code, Addison Wesley (2007), Code Refactorings

  4. Czysty kod. Podręcznik dobrego programisty and The Future of Programming (YouTube) by Robert C. Martin (Uncle Bob),

  5. 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

  6. On the cruelty of really teaching computer science by Edsger W. Dijkstra

Narzędzia

  1. Learn Enough by Michael Hartl

  2. Git

  3. Linters

  4. Code smell detectors (and brothers & sisters)

    1. Reek (for Ruby language)

    2. RuboCop – static code analyzer & style guide

    3. Flog – reports the most tortured code in an easy to read pain report – the higher the score, the more pain the code is in

    4. Flay – analyzes code for structural similarities

    5. SLOC – a tool for counting source lines of code

  5. Editors

Object Oriented Design (OOD)

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?

The BDD micro-process

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

A quantum point of view on programming
A quantum point of view on programming
Programmer State Attention Exclusion Principle

A programmer attentions should not occupy different states simultaneously.

Refactoring

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).

A refactoring example – Hide Delegate

Refactorings are designed to be safe transformations. But mistakes happens. So, use Git.

hide_delegate.rb
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:

  1. Create a delegating method on the Rectangle class. Test.

  2. For each client of the delegate adjust it to call the new method. Test.

  3. If no client needs to access the delegate any longer remove the Rectangle accessor for the delegate. Test.

Step 1
class Rectangle
  def left_edge
    @top_left.x
  end
end
Step 2
left_x = rect.left_edge
Step 3
class Rectangle
  attr_reader :width, :height
end

Smells ➨ Refactorings

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.

— Martin Fowler
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).

The refactoring cycle

Source: Refactoring in Ruby by W. C. Wake & K. Rutherford
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.
⚠️
Why Refactor?

Economics.

💡
Martin Fowler, Workflows of Refactoring

3 more reasons to use refactrorings: Litter Refactoring (ugly code), Comprehension Refactoring (I do not understand), Preparatory Refactoring (we should have done it this way); slides deck.

Automatyczne wyszukiwanie code smells w kodzie

Przykład automatycznego wyszukiwania code smells w pliku za pomocą programu reekCode smell detector for Ruby.

smelly.rb
# 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]

ABC – discovering pain code

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.

verse.rb
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:   <

Most common smells in the project

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

Smell of the Week – exercises to try

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

Misc Git

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.

About

OOD


Languages

Language:Ruby 100.0%