The presentation from VMWare Bulgaria, that was done during their guest lecture for the "Programming 101" course in Hack Bulgaria.
The presentation was done by Dimitar Dimitrov
4. Лекцията накратко
! High-level principles
• Добри практики на по-високо ниво (от обичайните design patterns)
! Micro-patterns and code idioms
• Добри практики на гранулярно ниво
2
5. Лекцията накратко
! High-level principles
• Добри практики на по-високо ниво (от обичайните design patterns)
! Micro-patterns and code idioms
• Добри практики на гранулярно ниво
! Anti-patterns
• Често срещани лоши практики или конструкции, за които съществува
алтернативен подход
2
6. Лекцията накратко
! High-level principles
• Добри практики на по-високо ниво (от обичайните design patterns)
! Micro-patterns and code idioms
• Добри практики на гранулярно ниво
! Anti-patterns
• Често срещани лоши практики или конструкции, за които съществува
алтернативен подход
! Examples of design patterns
• Примери от Java 7 SE API
!
2
7. Лекцията накратко
! High-level principles
• Добри практики на по-високо ниво (от обичайните design patterns)
! Micro-patterns and code idioms
• Добри практики на гранулярно ниво
! Anti-patterns
• Често срещани лоши практики или конструкции, за които съществува
алтернативен подход
! Examples of design patterns
• Примери от Java 7 SE API
!
! Disclaimer: Безогледна смес на български и английски ahead. Приемете на доверие,
че това спомага за краткостта и яснотата на изложението. Авторът приема
критики за грамотността си и преводаческите си способности.
2
10. High-level principles
! Като цяло не са обвързани с конкретен език или платформа.
! Могат да бъдат както implementation-centric, така и
practice-centric.
3
11. High-level principles
! Като цяло не са обвързани с конкретен език или платформа.
! Могат да бъдат както implementation-centric, така и
practice-centric.
! Design pattern-ите, които имат сходна структура и/или
употреба, обикновено изхождат от един и същ
implementation-centric принцип.
3
12. High-level principles
! Като цяло не са обвързани с конкретен език или платформа.
! Могат да бъдат както implementation-centric, така и
practice-centric.
! Design pattern-ите, които имат сходна структура и/или
употреба, обикновено изхождат от един и същ
implementation-centric принцип.
! Добрите практики, свързани с процеса на проектиране,
изграждане и поддържане на софтуер, обикновено изхождат
от practice-centric принципи.
• The Pragmatic Programmer, ISBN 978-0-2016-1622-4
3
13. High-level principles
! Като цяло не са обвързани с конкретен език или платформа.
! Могат да бъдат както implementation-centric, така и
practice-centric.
! Design pattern-ите, които имат сходна структура и/или
употреба, обикновено изхождат от един и същ
implementation-centric принцип.
! Добрите практики, свързани с процеса на проектиране,
изграждане и поддържане на софтуер, обикновено изхождат
от practice-centric принципи.
• The Pragmatic Programmer, ISBN 978-0-2016-1622-4
! Disclaimer: Термините implementation-centric и practice-centric са измислени от
автора и имат определени недостатъци.
3
16. Implementation-centric principles
! Четирите основни принципа на ООП
• Abstraction
• Encapsulation
• Inheritance
• Polymorphism
! Separation of concerns
• Свързан с encapsulation, loose coupling и strong cohesion
4
17. Implementation-centric principles
! Четирите основни принципа на ООП
• Abstraction
• Encapsulation
• Inheritance
• Polymorphism
! Separation of concerns
• Свързан с encapsulation, loose coupling и strong cohesion
! Single responsibility principle
4
18. Implementation-centric principles
! Четирите основни принципа на ООП
• Abstraction
• Encapsulation
• Inheritance
• Polymorphism
! Separation of concerns
• Свързан с encapsulation, loose coupling и strong cohesion
! Single responsibility principle
! DRY principle
• Свързан със single responsibility principle и maintainability
4
19. Implementation-centric principles
! Четирите основни принципа на ООП
• Abstraction
• Encapsulation
• Inheritance
• Polymorphism
! Separation of concerns
• Свързан с encapsulation, loose coupling и strong cohesion
! Single responsibility principle
! DRY principle
• Свързан със single responsibility principle и maintainability
! Design by contract
• Pre-conditions, post-conditions, invariants
• Особено важен при проектирането и създаването на API
4
22. Implementation-centric principles (2)
! Open-closed principle
• Компонентите трябва да са отворени за разширяване
• Но затворени за модификация
! Liskov substitution principle
• Обект от даден тип трябва да може да се използва прозрачно навсякъде,
където се очаква обект от базов на дадения тип (µs и ns)
5
23. Implementation-centric principles (2)
! Open-closed principle
• Компонентите трябва да са отворени за разширяване
• Но затворени за модификация
! Liskov substitution principle
• Обект от даден тип трябва да може да се използва прозрачно навсякъде,
където се очаква обект от базов на дадения тип (µs и ns)
! Law of Demeter
• “Не говори със съседа на съседа си”
• Ограничава методи на кои обекти могат да бъдат изпълнявани директно
5
24. Implementation-centric principles (2)
! Open-closed principle
• Компонентите трябва да са отворени за разширяване
• Но затворени за модификация
! Liskov substitution principle
• Обект от даден тип трябва да може да се използва прозрачно навсякъде,
където се очаква обект от базов на дадения тип (µs и ns)
! Law of Demeter
• “Не говори със съседа на съседа си”
• Ограничава методи на кои обекти могат да бъдат изпълнявани директно
! Inversion of control + Dependency injection
• Абстракцията не трябва да зависи от детайлите, детайлите трябва да
зависят от абстракцията
• Предпочитане на интерфейси пред абстрактни класове
5
26. Implementation-centric principles (3)
! Interface segregation principle
• Абстракции и зависимости трябва да бъдат ограничавани до възможно
най-малък интерфейс
• Ползвайте маркер интерфейси и интерфейси с един метод
6
27. Implementation-centric principles (3)
! Interface segregation principle
• Абстракции и зависимости трябва да бъдат ограничавани до възможно
най-малък интерфейс
• Ползвайте маркер интерфейси и интерфейси с един метод
! Acyclic dependency principle
• Структурата на зависимостите между компонентите не трябва да
съдържа циклични зависимости
6
28. Implementation-centric principles (3)
! Interface segregation principle
• Абстракции и зависимости трябва да бъдат ограничавани до възможно
най-малък интерфейс
• Ползвайте маркер интерфейси и интерфейси с един метод
! Acyclic dependency principle
• Структурата на зависимостите между компонентите не трябва да
съдържа циклични зависимости
! Principle of least astonishment
• Операциите трябва да имат ясен и консистентен резултат, разбираем от
името, документацията и очакваното приложение на метода или класа
• Много важен, когато имплементирате API
6
29. Implementation-centric principles (3)
! Interface segregation principle
• Абстракции и зависимости трябва да бъдат ограничавани до възможно
най-малък интерфейс
• Ползвайте маркер интерфейси и интерфейси с един метод
! Acyclic dependency principle
• Структурата на зависимостите между компонентите не трябва да
съдържа циклични зависимости
! Principle of least astonishment
• Операциите трябва да имат ясен и консистентен резултат, разбираем от
името, документацията и очакваното приложение на метода или класа
• Много важен, когато имплементирате API
! Principle of least resource usage
• Използвайте минимално количество ресурси
• Оптимизирайте само на базата на резултати от тестове, за да избегнете
premature optimization
6
31. Practice-centric principles
! Яснота и простота преди всичко
• Модулите, класовете, методите и др. трябва да бъдат възможно най-
малки, но не по-малки (Еinstein reference)
• Пазете се от семантично замърсяване или “излишен шум” в методите и
класовете си (припомнете си какво са cross-cutting concerns)
7
32. Practice-centric principles
! Яснота и простота преди всичко
• Модулите, класовете, методите и др. трябва да бъдат възможно най-
малки, но не по-малки (Еinstein reference)
• Пазете се от семантично замърсяване или “излишен шум” в методите и
класовете си (припомнете си какво са cross-cutting concerns)
! Принцип на Парето
• 80% от ефектите се причиняват от 20% от факторите
• Научете се да идентифицирате важните 20%
7
33. Practice-centric principles
! Яснота и простота преди всичко
• Модулите, класовете, методите и др. трябва да бъдат възможно най-
малки, но не по-малки (Еinstein reference)
• Пазете се от семантично замърсяване или “излишен шум” в методите и
класовете си (припомнете си какво са cross-cutting concerns)
! Принцип на Парето
• 80% от ефектите се причиняват от 20% от факторите
• Научете се да идентифицирате важните 20%
! Спазвайте създадените правила и конвенции
• Консистентността води до четимост и разбираемост
• Не нарушавайте конвенциите си заради малки оптимизации (защо?)
7
34. Practice-centric principles
! Яснота и простота преди всичко
• Модулите, класовете, методите и др. трябва да бъдат възможно най-
малки, но не по-малки (Еinstein reference)
• Пазете се от семантично замърсяване или “излишен шум” в методите и
класовете си (припомнете си какво са cross-cutting concerns)
! Принцип на Парето
• 80% от ефектите се причиняват от 20% от факторите
• Научете се да идентифицирате важните 20%
! Спазвайте създадените правила и конвенции
• Консистентността води до четимост и разбираемост
• Не нарушавайте конвенциите си заради малки оптимизации (защо?)
! Възползвайте се максимално от наличните инструменти
• Отделете време, за да оптимизирате максимално тези 20% от дейностите
си, които изпълнявате през 80% от времетo си
7
36. Practice-centric principles (2)
! Хващайте грешки, колкото се може по-рано
• Свързано не само с имплементацията, но и с целия процес на разработка
(Quality Engineering)
• Важно изискване: Признавайте грешките си
8
37. Practice-centric principles (2)
! Хващайте грешки, колкото се може по-рано
• Свързано не само с имплементацията, но и с целия процес на разработка
(Quality Engineering)
• Важно изискване: Признавайте грешките си
! Винаги планирайте и изпълнявайте, имайки предвид
контекста на вашия проект
• Пример: И производителността, и user experience-а са важни, но ако се
наложи, с кое от двете бихте направили компромис?
8
38. Practice-centric principles (2)
! Хващайте грешки, колкото се може по-рано
• Свързано не само с имплементацията, но и с целия процес на разработка
(Quality Engineering)
• Важно изискване: Признавайте грешките си
! Винаги планирайте и изпълнявайте, имайки предвид
контекста на вашия проект
• Пример: И производителността, и user experience-а са важни, но ако се
наложи, с кое от двете бихте направили компромис?
! Познавайте спецификите на проблемната област
• Познавайте лошите практики и техническите предизвикателства
• Идентифицирайте коя платформа ви върши най-добра работа,
използвайте идиомите на езика и проблемната област
8
39. Practice-centric principles (2)
! Хващайте грешки, колкото се може по-рано
• Свързано не само с имплементацията, но и с целия процес на разработка
(Quality Engineering)
• Важно изискване: Признавайте грешките си
! Винаги планирайте и изпълнявайте, имайки предвид
контекста на вашия проект
• Пример: И производителността, и user experience-а са важни, но ако се
наложи, с кое от двете бихте направили компромис?
! Познавайте спецификите на проблемната област
• Познавайте лошите практики и техническите предизвикателства
• Идентифицирайте коя платформа ви върши най-добра работа,
използвайте идиомите на езика и проблемната област
! Нито един принцип не е абсолютен
• Не следвайте сляпо принципи, които не ви носят добавена стойност
8
41. Micro-patterns and code idioms
! Като цяло обхващат добри практики със scope не повече
от тялото на един метод.
• Понякога разграничаването между pattern и micro-pattern е нетривиално
(Lazy loading)
9
42. Micro-patterns and code idioms
! Като цяло обхващат добри практики със scope не повече
от тялото на един метод.
• Понякога разграничаването между pattern и micro-pattern е нетривиално
(Lazy loading)
! Често са обвързани с платформата или езика, за които се
прилагат.
• Под code idiom често се разбира специфична за езика конструкция
(idiomatic code)
9
43. Micro-patterns and code idioms
! Като цяло обхващат добри практики със scope не повече
от тялото на един метод.
• Понякога разграничаването между pattern и micro-pattern е нетривиално
(Lazy loading)
! Често са обвързани с платформата или езика, за които се
прилагат.
• Под code idiom често се разбира специфична за езика конструкция
(idiomatic code)
! За разлика от design principles, code idioms по-често
биват неправилно използвани.
• Най-често всичко започва с доброто намерение на програмиста
• Понякога обаче това нарушава “Яснота и простота преди всичко”,
“Спазвайте създадените правила и конвенции” или “Не следвайте сляпо
принципи, които не ви носят добавена стойност”
9
45. Примери - micro-patterns
! Създаване и използване на immutable обекти
• Изключително полезно при multithreaded приложения, и не само там
• Какво недостатъци може да има?
10
46. Примери - micro-patterns
! Създаване и използване на immutable обекти
• Изключително полезно при multithreaded приложения, и не само там
• Какво недостатъци може да има?
! Ограничаване на scope-a на локалните променливи
• Ограничава възможността да злоупотребим, подпомага garbage collect-ването
• А ако пишем на JavaScript (как се определя scope-a там)?
10
47. Примери - micro-patterns
! Създаване и използване на immutable обекти
• Изключително полезно при multithreaded приложения, и не само там
• Какво недостатъци може да има?
! Ограничаване на scope-a на локалните променливи
• Ограничава възможността да злоупотребим, подпомага garbage collect-ването
• А ако пишем на JavaScript (как се определя scope-a там)?
! Lazy loading
• Може да подобри бързината и заеманата памет на приложението
• Рядко подобрението на бързината е фактор (виж http://goo.gl/5L4fi)
10
48. Примери - micro-patterns
! Създаване и използване на immutable обекти
• Изключително полезно при multithreaded приложения, и не само там
• Какво недостатъци може да има?
! Ограничаване на scope-a на локалните променливи
• Ограничава възможността да злоупотребим, подпомага garbage collect-ването
• А ако пишем на JavaScript (как се определя scope-a там)?
! Lazy loading
• Може да подобри бързината и заеманата памет на приложението
• Рядко подобрението на бързината е фактор (виж http://goo.gl/5L4fi)
! Defensive copying
• Може негативно да повлияе на бързината и заеманата памет, ако не се изисква
• Все пак по-добре да загубите производителност, отколкото да нарушите encapsulation-а
10
49. Примери - micro-patterns
! Създаване и използване на immutable обекти
• Изключително полезно при multithreaded приложения, и не само там
• Какво недостатъци може да има?
! Ограничаване на scope-a на локалните променливи
• Ограничава възможността да злоупотребим, подпомага garbage collect-ването
• А ако пишем на JavaScript (как се определя scope-a там)?
! Lazy loading
• Може да подобри бързината и заеманата памет на приложението
• Рядко подобрението на бързината е фактор (виж http://goo.gl/5L4fi)
! Defensive copying
• Може негативно да повлияе на бързината и заеманата памет, ако не се изисква
• Все пак по-добре да загубите производителност, отколкото да нарушите encapsulation-а
! Добавяне на static final модификатори
• Ползвайте го заради семантичния ефект, а не като performance optimization
• По подразбиране методите са виртуални в Java и невиртуални в C#
10
52. Примери - micro-patterns (2)
! Short-circuit булеви оператори
• mostLikelyFalse() && mostLikelyTrue()
• alwaysTrue() || alwaysThrowsException()
! Избягване на null референции
• CONST.equals(nullRef) и return itemArray != null ? itemArray : [];
• Може да бъде ненужно или нежелано
• ако прикрива по-късен NullPointerException по време на изпълнение
• ако между null и [] има семантична разлика
11
53. Примери - micro-patterns (2)
! Short-circuit булеви оператори
• mostLikelyFalse() && mostLikelyTrue()
• alwaysTrue() || alwaysThrowsException()
! Избягване на null референции
• CONST.equals(nullRef) и return itemArray != null ? itemArray : [];
• Може да бъде ненужно или нежелано
• ако прикрива по-късен NullPointerException по време на изпълнение
• ако между null и [] има семантична разлика
! Достъпване и промяна на полета през методи
• Почти винаги трябва да се използва
• Какво става, ако за класа Person, трябва да връщате не this.age, a this.age
- 10, ако FEMALE.equals(this.sex)?
• Изключение правят чистите data обекти с ограничена (непублична)
видимост
11
56. Anti-patterns
! Често срещани шаблони с идентифицирани недостатъци,
за които съществува алтернативен подход.
! Могат да бъдат:
12
57. Anti-patterns
! Често срещани шаблони с идентифицирани недостатъци,
за които съществува алтернативен подход.
! Могат да бъдат:
• Контрапродуктивни навици
12
58. Anti-patterns
! Често срещани шаблони с идентифицирани недостатъци,
за които съществува алтернативен подход.
! Могат да бъдат:
• Контрапродуктивни навици
• Лоши конструкции, създадени с добри намерения
12
59. Anti-patterns
! Често срещани шаблони с идентифицирани недостатъци,
за които съществува алтернативен подход.
! Могат да бъдат:
• Контрапродуктивни навици
• Лоши конструкции, създадени с добри намерения
• Лоши конструкции, появяващи се с течение на разработката
12
60. Anti-patterns
! Често срещани шаблони с идентифицирани недостатъци,
за които съществува алтернативен подход.
! Могат да бъдат:
• Контрапродуктивни навици
• Лоши конструкции, създадени с добри намерения
• Лоши конструкции, появяващи се с течение на разработката
! Code smells
12
61. Anti-patterns
! Често срещани шаблони с идентифицирани недостатъци,
за които съществува алтернативен подход.
! Могат да бъдат:
• Контрапродуктивни навици
• Лоши конструкции, създадени с добри намерения
• Лоши конструкции, появяващи се с течение на разработката
! Code smells
• индикация или симптом за съществуването на по-сериозен проблем
12
62. Anti-patterns
! Често срещани шаблони с идентифицирани недостатъци,
за които съществува алтернативен подход.
! Могат да бъдат:
• Контрапродуктивни навици
• Лоши конструкции, създадени с добри намерения
• Лоши конструкции, появяващи се с течение на разработката
! Code smells
• индикация или симптом за съществуването на по-сериозен проблем
• code duplication
12
63. Anti-patterns
! Често срещани шаблони с идентифицирани недостатъци,
за които съществува алтернативен подход.
! Могат да бъдат:
• Контрапродуктивни навици
• Лоши конструкции, създадени с добри намерения
• Лоши конструкции, появяващи се с течение на разработката
! Code smells
• индикация или симптом за съществуването на по-сериозен проблем
• code duplication
• прекалено дълги методи
12
64. Anti-patterns
! Често срещани шаблони с идентифицирани недостатъци,
за които съществува алтернативен подход.
! Могат да бъдат:
• Контрапродуктивни навици
• Лоши конструкции, създадени с добри намерения
• Лоши конструкции, появяващи се с течение на разработката
! Code smells
• индикация или симптом за съществуването на по-сериозен проблем
• code duplication
• прекалено дълги методи
• и разбира се, прекалено дълги класове
12
65. Anti-patterns
! Често срещани шаблони с идентифицирани недостатъци,
за които съществува алтернативен подход.
! Могат да бъдат:
• Контрапродуктивни навици
• Лоши конструкции, създадени с добри намерения
• Лоши конструкции, появяващи се с течение на разработката
! Code smells
• индикация или симптом за съществуването на по-сериозен проблем
• code duplication
• прекалено дълги методи
• и разбира се, прекалено дълги класове
• код с няколко нива на conditional nesting
12
66. Anti-patterns
! Често срещани шаблони с идентифицирани недостатъци,
за които съществува алтернативен подход.
! Могат да бъдат:
• Контрапродуктивни навици
• Лоши конструкции, създадени с добри намерения
• Лоши конструкции, появяващи се с течение на разработката
! Code smells
• индикация или симптом за съществуването на по-сериозен проблем
• code duplication
• прекалено дълги методи
• и разбира се, прекалено дълги класове
• код с няколко нива на conditional nesting
• методи с прекалено много аргументи
12
68. Design Patterns и Java 7 SE API
! Singleton
• System.console(), Runtime.getRuntime(), Collections.EMPTY_MAP
13
69. Design Patterns и Java 7 SE API
! Singleton
• System.console(), Runtime.getRuntime(), Collections.EMPTY_MAP
! Factory method/Factory
• Boolean.valueOf(String s), Class.newInstance() (макар че Class вече е
параметризиран тип, типът на създадената инстанция е конкретен)
13
70. Design Patterns и Java 7 SE API
! Singleton
• System.console(), Runtime.getRuntime(), Collections.EMPTY_MAP
! Factory method/Factory
• Boolean.valueOf(String s), Class.newInstance() (макар че Class вече е
параметризиран тип, типът на създадената инстанция е конкретен)
! Abstract Factory
• URL.openConnection(), Arrays.asList(T... a) (винаги връща инстанция на
ArrayList), Collections.unmodifiableList(List<? extends T> c) (винаги връща
инстанция на inner class, невидим извън самия JDK)
13
71. Design Patterns и Java 7 SE API
! Singleton
• System.console(), Runtime.getRuntime(), Collections.EMPTY_MAP
! Factory method/Factory
• Boolean.valueOf(String s), Class.newInstance() (макар че Class вече е
параметризиран тип, типът на създадената инстанция е конкретен)
! Abstract Factory
• URL.openConnection(), Arrays.asList(T... a) (винаги връща инстанция на
ArrayList), Collections.unmodifiableList(List<? extends T> c) (винаги връща
инстанция на inner class, невидим извън самия JDK)
! Prototype
• Object.clone() (клонирането на обекти в Java е доста “дълбока” тема; виж
Effective Java, 2nd Edition, Item 11)
13
72. Design Patterns и Java 7 SE API
! Singleton
• System.console(), Runtime.getRuntime(), Collections.EMPTY_MAP
! Factory method/Factory
• Boolean.valueOf(String s), Class.newInstance() (макар че Class вече е
параметризиран тип, типът на създадената инстанция е конкретен)
! Abstract Factory
• URL.openConnection(), Arrays.asList(T... a) (винаги връща инстанция на
ArrayList), Collections.unmodifiableList(List<? extends T> c) (винаги връща
инстанция на inner class, невидим извън самия JDK)
! Prototype
• Object.clone() (клонирането на обекти в Java е доста “дълбока” тема; виж
Effective Java, 2nd Edition, Item 11)
! Flyweight
• Boolean.valueOf(String s), Collections.emptyMap()
13
74. Design Patterns и Java 7 SE API (2)
! Adapter
• InputStreamReader(InputStream)
14
75. Design Patterns и Java 7 SE API (2)
! Adapter
• InputStreamReader(InputStream)
! Composite
• java.awt.Container.add(Component comp) (връща инстанция на Component)
• Collection.addAll(Collection<? extends e> c) is not Composite (добавяната
колекция не бива запазена)
14
76. Design Patterns и Java 7 SE API (2)
! Adapter
• InputStreamReader(InputStream)
! Composite
• java.awt.Container.add(Component comp) (връща инстанция на Component)
• Collection.addAll(Collection<? extends e> c) is not Composite (добавяната
колекция не бива запазена)
! Decorator
• Collections.unmodifiableList(List<? extends T> c) (тъй като поведението
се променя)
14
77. Design Patterns и Java 7 SE API (2)
! Adapter
• InputStreamReader(InputStream)
! Composite
• java.awt.Container.add(Component comp) (връща инстанция на Component)
• Collection.addAll(Collection<? extends e> c) is not Composite (добавяната
колекция не бива запазена)
! Decorator
• Collections.unmodifiableList(List<? extends T> c) (тъй като поведението
се променя)
! Proxy
• subtypes of java.lang.reflect.Proxy
• създавани чрез статичния factory method newProxyInstance(ClassLoader
loader, Class<?>[] interfaces, InvocationHandler h)
14