├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── build.sbt
├── project
├── build.properties
└── plugins.sbt
└── src
└── test
└── scala
└── com
└── github
└── dnvriend
├── TestSpec.scala
├── oo
├── behavioral
│ ├── CommandPatternTest.scala
│ ├── IteratorPatternTest.scala
│ ├── ObserverPatternTest.scala
│ ├── StatePatternTest.scala
│ └── TemplateMethodPatternTest.scala
├── creational
│ ├── FactoryPatternTest.scala
│ └── SingletonPatternTest.scala
└── structural
│ ├── AdapterPatternTest.scala
│ ├── CompositionPatternTest.scala
│ ├── DecoratorPatternTest.scala
│ ├── FacadePatternTest.scala
│ └── ProxyPatternTest.scala
└── scala
├── reflect
└── TypeTagTest.scala
└── selftype
└── SelfTypeTest.scala
/.gitignore:
--------------------------------------------------------------------------------
1 | /RUNNING_PID
2 | /logs/
3 | /project/*-shim.sbt
4 | /project/project/
5 | /project/target/
6 | /target/
7 | .idea/
8 | *.iml
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: scala
2 | scala:
3 | - 2.11.7
4 | sudo: false
5 | sbt_args: -no-colors -J-Xss2m
6 | jdk:
7 | - oraclejdk8
8 | branches:
9 | only:
10 | - master
11 | notifications:
12 | email:
13 | - dnvriend@gmail.com
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Design Patterns Study
2 | This project is a study into object oriented and functional design patterns, implemented in Scala. It is for my own study
3 | and future reference but if you find the subject matter interesting and if the information here helps you in your study
4 | then I would be glad! :)
5 |
6 | [](http://www.apache.org/licenses/LICENSE-2.0.txt)
7 |
8 | I'm confident in having a good understanding of design patterns, and enough insight / experience when to apply them
9 | is key into creating agile software and therefor supporting the goals of agile software development like [Disciplined
10 | Agile Delivery](http://www.disciplinedagiledelivery.com/).
11 |
12 | > Patterns always have two parts: the how and the when. Not just do you need to know how to implement them, you also have to know when to use them and when to leave them alone. Martin Fowler
13 |
14 | # Core design principles
15 | - [Core Design Principles for Software Developers by Venkat Subramaniam](https://www.youtube.com/watch?v=llGgO74uXMI)
16 |
17 | # What are Patterns?
18 | There are different categories of software patterns:
19 | * Architectural patterns: big broad things that can describe an entire computer system. They are programming language
20 | agnostic, but talk about how all the different subsystems and components fit together,
21 | * Design patterns: patterns that describe how things happen in a single component, how a program is structured, how the data flows,
22 | how the execution flows, etc..
23 | * Idioms: (pattern oriented software); specific to a single programming language; examples of a design pattern
24 | implemented in a programming language, or smaller localized patterns that are seen in a particular programming language
25 |
26 | # What are anti-patterns?
27 | An anti-pattern is the opposite of a pattern; while it too describes a recurring solution to a commonly encountered problem, the solution is typically dysfunctional or ineffective, and has negative impacts on the “health” of the software (in terms of maintainability, extensibility, robustness, etc.). Anti-patterns serve a similar purpose to patterns; the description of the anti-pattern might illustrate a typical implementation of the anti-pattern, explain the context it generally occurs in, and show how the implementation results in problems for the software.
28 |
29 | A potential problem with the concept of a design anti-pattern is that it might discourage `critical thought` about the applicability of the pattern. A design that may be inappropriate in some contexts may be a sensible decision in others; a solution might be discarded after being recognised as an anti-pattern, even though it would be a good fit for the problem at hand.
30 |
31 | # Why do we need patterns?
32 | - We need to know design patterns to find solutions for frequently occurring problems. And we want to reuse these
33 | solutions whenever we face a similar situation in the future.
34 | - These are one kind of template to address solutions in many different situations.
35 | - In other words, these are the descriptions of how different objects and their respective classes
36 | solve a design problem in a specific context.
37 |
38 | # Object Oriented Design Patterns
39 | The following (23) patterns describe creational, structural and behavioral patterns are fully described in the Gang of Four
40 | book 'Design Patterns: Elements of Reusable Object-Oriented Software'
41 |
42 | ## Creational (5)
43 | Creational patterns are patterns that create object for you; hence creational. The goal here is, rather than having your
44 | code instant object directly and therefor having all the logic about how to create (sometimes complex initialization
45 | logic surrounding objects), the creational pattern will do that for you. This has a second benefit, in that having all
46 | the creational logic in one place, changes to that logic will propagate to where the new object is needed.
47 |
48 | Creational patterns provide guidance on the creation of objects. They help hide the details of the object instantiation
49 | from the code that uses those objects. That is they make an application independent of how its objects are created,
50 | composed and represented. This leads to high cohesion between the objects and their users, but low couple between the
51 | users and the way the objects are created. For example, if I have a Java interface that is implemented by three different
52 | classes, then using a Factory pattern I might instantiate one of the three classes depending on the current situation.
53 | All the user of the object returned needs to know is what interface they all implement. The actual implementation may change
54 | each time the factory is used, but this detail is hidden.
55 |
56 | There are 5 different patterns within the creational patterns category. They are `Factory Method`, `Abstract Factory`,
57 | `Builder`, `Prototype` and `Singleton`. These patterns are presented below:
58 |
59 | * __Factory method pattern__: The `factory method pattern` provides a pattern that describes the use of a factory class (or method)
60 | for constructing objects. The methods on the factory return objects that implement a given interface. The user of the factory only knows about the interface.
61 | Thus different objects can be created depending on the current situation (as long as they implement the interface). creates objects without specifying the
62 | exact class to create.
63 | * Abstract factory pattern: The `abstract factory pattern` describes a pattern for creating families of related or dependent objects.
64 | * Builder pattern: The `builder pattern` separates out the construction of a complex object from its use. Thus the client can specify what
65 | type of object is required and what its content might be, but never need to know about how that object is constructed and initialised.
66 | * Prototype pattern: The `prototype pattern` allows a user object to create a customized object, based on a prototype of what is required. That is,
67 | the pattern describes how a new object can be created based on a customisation of an existing object.
68 | * __Singleton pattern__: The `singleton pattern` describes a class that can only have one object constructed for it. That is, unlike other objects
69 | it should not be possible to obtain more than one instance within the same virtual machine. Thus the Singleton pattern ensures that only one instance
70 | of a class is created. All objects that use an instance of that class use the same instance. The motivation behind this pattern is that some classes,
71 | typically those classes that involve the central management of a resource, should have exactly one instance. For example, a object that managements
72 | the reuse of database connections (i.e. a connection pool) could be a singleton.
73 |
74 | ## Structural (7)
75 | Structural patterns describe the `organization of objects`. That is how classes and objects are composed to form larger structures.
76 | For example a large department store near where I live, appears form the outside to be a single entity with a very grand frontage.
77 | However, behind this frontage is a completely new shop containing various independent stores. This means that as a customer I see
78 | form the outside a single and quite grand whole. But form the inside there are multiple smaller shops/brands all working together.
79 | This is the essence of the `Facade` pattern.
80 |
81 | Structural patterns concern class and object composition; hence structural. They use `inheritance` to `compose` interfaces
82 | and define ways to compose objects to obtain new functionality.
83 |
84 | * __Proxy pattern:__ provides a placeholder for another object to control access, reduce cost, and reduce complexity.
85 | * Flyweight pattern: reduces the cost of creating and manipulating a large number of similar objects.
86 | * Bridge pattern: decouples an abstraction from its implementation so that the two can vary independently.
87 | * __Facade pattern:__ provides a simplified interface to a large body of code.
88 | * __Decorator pattern:__ dynamically adds/overrides behaviour in an existing method of an object.
89 | * __Adapter pattern:__ allows classes with incompatible interfaces to work together by wrapping its own interface around that of an already existing class.
90 | * __Composite pattern:__ composes zero-or-more similar objects so that they can be manipulated as one object.
91 |
92 | ## Behavioral (11)
93 | Behavioral patterns are specifically concerned with `communication` between objects, hence behavioral. Here our concentration is
94 | on algorithms and the assignment of the critical responsibilities among the objects. We also need to focus on the communication
95 | between them. We need to take a closer look at the way those objects are interconnected.
96 |
97 | Behavioural patterns are concerned with organizing, managing and assigning responsibilities to objects `during execution`.
98 | That is, the focus of the behavioral patterns are on the communication between objects during the execution of some task.
99 | Typically, these patterns characterize complex control flows that are difficult to follow at runtime. They therefore help to
100 | shift the emphasis away from the low level flow of control to the higher level object interactions.
101 |
102 | * Chain of responsibility pattern: delegates commands to a chain of processing objects.
103 | * __Command pattern:__ creates objects which encapsulate actions and parameters.
104 | * Interpreter pattern: implements a specialized language.
105 | * __Iterator pattern:__ accesses the elements of an object sequentially without exposing its underlying representation.
106 | * [Mediator pattern](https://sourcemaking.com/design_patterns/mediator): allows loose coupling between classes by being the only class that has detailed knowledge of their methods.
107 | * Memento pattern: provides the ability to restore an object to its previous state (undo).
108 | * __Observer pattern:__ is a publish/subscribe pattern which allows a number of observer objects to see an event.
109 | * __State pattern:__ allows an object to alter its behavior when its internal state changes.
110 | * Strategy pattern: allows one of a family of algorithms to be selected on-the-fly at runtime.
111 | * __Template method pattern:__ defines the skeleton of an algorithm as an abstract class, allowing its subclasses to provide concrete behavior.
112 | * Visitor pattern: separates an algorithm from an object structure by moving the hierarchy of methods into one object.
113 |
114 | # Replacing Object Oriented Patterns with Functional Patterns
115 |
116 | * Replacing Functional Interface
117 | * Replacing state-carrying functional interface
118 | * Replacing command
119 | * Replacing Builder for Immutable Objects
120 | * Replacing Iterator
121 | * Replacing Template Method
122 | * Replacing Strategy
123 | * Replacing Null Object
124 | * Replcing Decorator
125 | * Replacing Visitor
126 | * Replacing Dependency Injection
127 |
128 | # Functional Patterns
129 |
130 | * Monoid Pattern
131 | * Functor Pattern
132 | * Applicative Functor Pattern
133 | * Type Class Pattern
134 | * Tail Recursion
135 | * Mutual Recursion
136 | * Filter-Map-Reduce
137 | * Chain of operations
138 | * Function Builder
139 | * Memoization
140 | * Lazy Sequence
141 | * Focused Mutability
142 | * Customized Control Flow
143 | * Domain-Specific Language
144 |
145 | # Polymorphism
146 |
147 | * [Parameteric polymorphism](http://eed3si9n.com/learning-scalaz/polymorphism.html#Subtype+polymorphism),
148 | * [Subtype polymorphism](http://eed3si9n.com/learning-scalaz/polymorphism.html#Ad-hoc+polymorphism),
149 | * [Ad-hoc polymorphism](http://eed3si9n.com/learning-scalaz/polymorphism.html#Ad-hoc+polymorphism) [Debasish Ghosh - Scala Implicits : Type Classes Here I Come](http://debasishg.blogspot.com/2010/06/scala-implicits-type-classes-here-i.html),
150 |
151 | # Registry
152 | A `registry` is a list of items with pointers for where to find the items, like the index on a database table or the
153 | card catalog for a library. If you lose a `registry`, the items still exist; you just may need to reindex them.
154 |
155 | # Repository
156 | A `repository` is an abstraction of a collection of objects. A `repository` stores the actual items (objects),
157 | like a database table itself or a library's shelves of books. If you lose a `repository`, the items are gone.
158 |
159 | The repository is closer to the domain. It acts on aggregate roots (domain objects/entity) and would use multiple
160 | DAOs to build a single entity.
161 |
162 | # Spring repository
163 | [Documentation](http://docs.spring.io/spring-data/data-commons/docs/current/reference/html/#repositories)
164 |
165 | # CQRS Domain Repository
166 | The CQRS domain repository gets an aggregate root by its id, and loads/saves the generated events.
167 |
168 | # DAO pattern
169 | [DAO Pattern](http://www.tutorialspoint.com/design_pattern/data_access_object_pattern.htm)
170 |
171 | The Data Access Object pattern is used to separate low level data accessing API operations from high level business services.
172 | Following are the participants in Data Access Object Pattern.
173 |
174 | * __Data Access Object Interface__: an `interface` defines the standard operations to be performed on a model object(s).
175 | * __Data Access Object concrete class__: concrete class that implements the above interface. This class is responsible to get data from a data source which can be database / xml or any other storage mechanism.
176 | * __Model Object or Value Object__: the object that is managed by the DAO. It is usually a simple value object like eg. case classes.
177 |
178 | The DAO makes sure that the specific implementation is abstracted away behind an `interface` so that the implementation can
179 | be switched. It also ensures the correct modularization and cohesion of functionality.
180 |
181 | A DAO returns `data` in the broadest sense of the word and is the very definition (a data access object). How the DAO
182 | accesses the data, whether it be by accessing a queue, an XML file, or by querying one or more tables is not defined.
183 |
184 | So, the DAO deals with persistence issues and is an abstraction of data persistence. Its also closer to the database / persistency
185 | than the `repository` would be. A `repository` only deals with `domain objects`
186 |
187 | In the trenches, DAOs are sometimes called `providers` and Martin Fowler defines them as [Table Data Gateway pattern](http://martinfowler.com/eaaCatalog/tableDataGateway.html).
188 |
189 | # Facade pattern
190 | The facade pattern is used to hide the `call complexity` of a system. It provides a simple abstraction, a single method,
191 | that abstracts away all the `call complexity` to several subsystems. For example, a client does not have to know that, in
192 | order to return a result, a number of subsystems (local or remote) are involved.
193 |
194 | So, facade deals with control and workflow.
195 |
196 | # Service
197 | From: [StackExchange](http://programmers.stackexchange.com/questions/218011/how-accurate-is-business-logic-should-be-in-a-service-not-in-a-model)
198 |
199 | It is not easy to define what the responsibilities of a `service` are. `Service` is not a canonical or generic software term.
200 | In fact, the suffix `Service` on a class name is a lot like the much-maligned `Manager`: It tells you almost nothing about what
201 | the object actually does.
202 |
203 | In reality, what a `service` ought to do is highly architecture-specific, so first you have to specify the `architecture` and then the
204 | `service`'s responsibility will become clear.
205 |
206 | ## Traditional Layered Architecture
207 | In a traditional layered architecture, `service` is literally synonymous with `business logic layer`. It's the layer between UI
208 | and Data. Therefore, all business rules go into services. The data layer should only understand basic CRUD operations, and the
209 | UI layer should deal only with the mapping of presentation Data Transfer Objects (DTOs) to and from the business objects.
210 |
211 | ## RPC style
212 | In an RPC-style distributed architecture (SOAP, UDDI, BPEL, etc.), the `service` is the logical version of a physical endpoint.
213 | It is essentially a collection of operations that the maintainer wishes to provide as a public API. Various best practices guides
214 | explain that a `service` operation should in fact be a business-level operation (capabilities) and not CRUD, and I tend to agree.
215 |
216 | However, because routing everything through an actual remote service can seriously hurt performance, it's normally best not to have
217 | these services actually implement the business logic themselves; instead, they should wrap an "internal" set of business objects.
218 | A single service might involve one or several business objects.
219 |
220 | ## Model-View-Controller (MVC)
221 | In an MVP/MVC/MVVM/MV* architecture, services don't exist at all. Or if they do, the term is used to refer to any generic object
222 | that can be injected into a controller or view model. The business logic is in your model. If you want to create "service objects"
223 | to orchestrate complicated operations, that's seen as an implementation detail. A lot of people, sadly, implement MVC like this, but
224 | it's considered an anti-pattern ([Anemic Domain Model](http://en.wikipedia.org/wiki/Anemic_domain_model)) because the model itself does nothing, it's just a bunch of properties for the UI.
225 |
226 | Some people mistakenly think that taking a 100-line controller method and shoving it all into a service somehow makes for a better architecture.
227 | It really doesn't; all it does is add another, probably unnecessary layer of indirection. Practically speaking, the controller is still doing
228 | the work, it's just doing so through a poorly named `helper` object. I highly recommend [Jimmy Bogard's Wicked Domain Models presentation](http://vimeo.com/43598193)
229 | for a clear example of how to turn an [anemic domain model](http://en.wikipedia.org/wiki/Anemic_domain_model) into a useful one. It involves
230 | careful examination of the models you're exposing and which operations are actually valid in a business context.
231 |
232 | For example, if your database contains Orders, and you have a column for Total Amount, your application probably shouldn't be allowed
233 | to actually change that field to an arbitrary value, because (a) it's history and (b) it's supposed to be determined by what's in the
234 | order as well as perhaps some other time-sensitive data/rules. Creating a service to manage Orders does not necessarily solve this problem,
235 | because user code can still grab the actual Order object and change the amount on it. Instead, the order itself should be responsible for
236 | ensuring that it can only be altered in safe and consistent ways.
237 |
238 | ## Domain Driven Design (DDD)
239 | In DDD, `services` are meant specifically for the situation [when you have an operation that doesn't properly belong to __any__ aggregate root](http://gorodinski.com/blog/2012/04/14/services-in-domain-driven-design-ddd/).
240 | You have to be careful here, because often the need for a `service` can imply that you didn't use the correct roots. But assuming you did,
241 | a `service` is used to coordinate operations across multiple roots, or sometimes to handle concerns that don't involve the domain model at all
242 | (such as, perhaps, writing information to a BI/OLAP database).
243 |
244 | One notable aspect of the DDD service is that it is allowed to use [transaction scripts](http://martinfowler.com/eaaCatalog/transactionScript.html).
245 | When working on large applications, you're very likely to eventually run into instances where it's just way easier to accomplish something with a
246 | T-SQL or PL/SQL procedure than it is to fuss with the domain model. This is OK, and it belongs in a `service`.
247 |
248 | This is a radical departure from the layered-architecture definition of services. A `service layer` encapsulates domain objects; a `DDD service`
249 | encapsulates whatever isn't in the domain objects and doesn't make sense to be.
250 |
251 | ## SOA
252 | In a Service-Oriented Architecture, a `service` is considered to be the technical authority for a business capability. That means that it is the
253 | exclusive owner of a certain subset of the business data and nothing else is allowed to touch that data - not even to just read it.
254 |
255 | By necessity, `services` are actually an end-to-end proposition in an SOA. Meaning, a `service` isn't so much a specific component as an
256 | entire stack, and your entire application (or your entire business) is a set of these services running side-by-side with no intersection
257 | except at the messaging and UI layers. Each service has its own data, its own business rules, and its own UI. They don't need to orchestrate
258 | with each other because they are supposed to be business-aligned - and, like the business itself, each `service` has its own set of
259 | responsibilities and operates more or less independently of the others.
260 |
261 | So, by the SOA definition, every piece of business logic anywhere is contained within the `service`, but then again, so is the entire system.
262 | Services in an SOA can have components, and they can have endpoints, but it's fairly dangerous to call any piece of code a `service` because it
263 | conflicts with what the original "S" is supposed to mean.
264 |
265 | Since SOA is generally pretty keen on messaging, the operations that you might have packaged in a `service` before are generally encapsulated
266 | in handlers, but the multiplicity is different. Each handler handles one message type, one operation. It's a strict interpretation of the
267 | [Single Responsibility Principle](http://en.wikipedia.org/wiki/Single_responsibility_principle), but makes for great maintainability because
268 | every possible operation is in its own class. So you don't really need centralized business logic, because commands represents business operations
269 | rather than technical ones.
270 |
271 | ## Conclusion
272 | Ultimately, in any architecture you choose, there is going to be some component or layer that has most of the business logic. After all,
273 | if business logic is scattered all over the place then you just have spaghetti code. But whether or not you call that component a `service`,
274 | and how it's designed in terms of things like number or size of operations, depends on your architectural goals.
275 |
276 | There's no right or wrong answer, only what applies to your situation.
277 |
278 | To add to the discussion, services can be:
279 |
280 | - Stateless, Stateful or ,
281 | - Be `local` or `remote`
282 | - Will be used by clients (local or remote clients) by means of a `Service Contract` ie. `interface`
283 | - Dependent on the technology (stack), can be supplied with container services like security and transactions.
284 |
285 | # Where to put business logic
286 | In JavaEE the place to put business logic is in the `business logic` layer or simply `logic`. These are objects that
287 | communicate with each other, optionally receiving services like security and transactions.
288 |
289 | As we are using Actors, the place to put business logic are in traits. When using functional style of programming,
290 | the Actor can manage the state and the business logic can be mixed in and thus reused where appropriate.
291 |
292 | # Anemic Domain Model
293 | [Anemic domain model](https://en.wikipedia.org/wiki/Anemic_domain_model) is the use of a software domain model where the
294 | domain objects contain little or no business logic (validations, calculations, business rules etc.). This pattern was first
295 | [described by Martin Fowler](https://en.wikipedia.org/wiki/Anemic_domain_model), who considers the practice an anti-pattern,
296 | which doesn't mean that it is an anti-pattern, it is the opinion of Martin Fowler.
297 |
298 | In an anemic domain design, business logic is typically implemented in separate classes which transform the state of the
299 | domain objects. Fowler calls such external classes [transaction scripts](http://martinfowler.com/eaaCatalog/transactionScript.html).
300 |
301 | This pattern is a common approach in Java applications, possibly encouraged by technologies such as early versions of EJB's Entity Beans, as well as in .NET applications following the Three-Layered Services Application architecture where such objects fall into the category of "Business Entities" (although Business Entities can also contain behavior).
302 |
303 | ## Reasons why models are anemic
304 | * Near-total absence of business logic, as in an application which is primarily an assemblage of CRUD screens?
305 | * Service-oriented architecture in which the 'domain objects' are in fact data transfer objects?
306 | * Political or pragmatic considerations such as code ownership or forward/backward compatibility that excessively impede refactoring?
307 | * Applying procedural/relational design in an otherwise object-oriented language?
308 |
309 | In any case, if [I]((http://stackoverflow.com/questions/1156644/anemic-domain-models-vs-domain-model-in-a-simple-domain-driven-design)) were to pick a simple rule of thumb for the boundary between domain model logic and service logic, it would be that interacting with related objects is fine within the domain, while accessing the "outside world" (user interface, web services, etc) probably doesn't belong in the domain model.
310 |
311 | ## Another point of view
312 | * Anemic domain model = database tables mapped to objects (only field values, no real behavior)
313 | * Rich domain model = a collection of objects that expose behavior
314 |
315 | If you want to create a simple CRUD application, maybe an anemic model with a classic MVC framework is enough. But if you want to implement some kind of logic, __anemic model means that you will not do object oriented programming__.
316 |
317 | __Note:__ Object behavior has nothing to do with persistence. A different layer (Gateways/DAO's, Data Mappers, Repositories etc.) is responsible for persisting domain objects. The key point is that the domain model implements the logic and operates on the state.
318 |
319 | ## Tiers vs Layers
320 | A tier is a module boundary that exists to provide isolation between major components of a system.
321 | A presentation tier that is visible to the user is separate from the application tier which encompasses
322 | business logic. In turn the data tier is another separate system that can manage, persist and provide access to data.
323 | Components grouped in a tier can physically reside on different infrastructure.
324 |
325 | Layers are logical slices that carry our specific responsibilities in an application.
326 | Each tier can have multiple layers within it responsible for different elements of functionality such as domain services.
327 |
328 | ## DTO’S, DDD & The Anemic Domain Model
329 | [I](http://elegantcode.com/2009/11/13/dtos-ddd-the-anemic-domain-model/) agree that an anemic domain model is bad, if there is no behavior then what’s the point right?
330 |
331 | __DTO:__ To me, a DTO moves data between ‘tiers’. They are the packaged data ready for transport. A JSON object is also a DTO.
332 |
333 | __Read model:__ This would be a different model than your real Domain model. A Read model is very lightweight, `thin` and anemic. Its purpose is to serve aggregated data to a specific screen or message. A DTO, to me, can be a read model, as too could be a View Model.
334 |
335 | __The domain model:__ rich and full of behavior. This model is most valuable when performing complex business rules during the saving and updating of data within a given transaction. It can also be used to read data too.
336 |
337 | Splitting the models allows the reads & writes to fluctuate independently, so which leads to higher maintainability. These models can also run on different tiers/nodes to increase scalability (read/cache tier, write tier), which are all choices.
338 |
339 | At some point, whether off a view or an inbound DTO, there will be mapping back into the domain model. This ‘friction’ or ‘impedance’ is pretty easy to manage using an assembler/translator, or a tool like AutoMapper.
340 |
341 | Greg Young & Udi Dahan take this concept further and apply a programming principle called [Command-Query Responsibility Separation/Seggregation](http://martinfowler.com/bliki/CQRS.html) with distributed programming and SOA.
342 |
343 | ## The Anaemic Domain Model (ADM) is no Anti-Pattern
344 | [I](https://blog.inf.ed.ac.uk/sapm/2014/02/04/the-anaemic-domain-model-is-no-anti-pattern-its-a-solid-design/) contend that such an anti-pattern is the `Anaemic Domain Model (ADM)`. The ADM is considered by these authors __as a failure to model a solution in an Object-Oriented manner__, instead relying on a procedural design to express business logic (which is a perfect definition of the ADM). This approach is contrasted with the Rich Domain Model (RDM), in which classes representing domain entities encapsulate all business logic and data. While the ADM may certainly be a poor design choice in some systems, it is not obvious that this is the case for all systems.
345 |
346 | In some scenarios, the ADM appears be an reasonable choice of design, in terms of adherence to the
347 | [SOLID principles of Object-Oriented design](https://en.wikipedia.org/wiki/SOLID_(object-oriented_design).
348 | The SOLID principles are guidelines which seek to balance implementation simplicity, scalability, and robustness.
349 | Specifically, by contrasting an ADM design with an RDM design for a hypothetical problem.
350 |
351 | I will attempt to show that ADM is a better fit for the SOLID principles than the RDM solution.
352 |
353 | An ADM consists of a set of behaviour-free classes containing business data required to model the domain. These classes typically contain little or no business logic (validations, calculations, business rules etc..), instead, business logic is implemented by a domain service/logic layer. The domain service/logic layer consists of a set of types and functions which process the domain models as dictated by business rules. The argument against this approach is that the data and methods are divorced, violating a fundamental principle of Object-Oriented design by removing the capability of the domain model to enforce its own invariants.
354 |
355 | In contrast, while an RDM consists of the same set of types containing necessary business data, the domain logic is also entirely resident on these domain entities, expressed as methods. The RDM then aligns well with the related concepts of encapsulation and information hiding; as Michael L. Scott states, `Encapsulation mechanisms enable the programmer to group data and the subroutines that operate on them together in one place, and to hide irrelevant details from the users of an abstraction`.
356 |
357 | In an RDM, the domain service/logic layer is either extremely thin or non-existent, and all domain rules are implemented via domain models. The contention is that domain entities in a RDM are then entirely capable of enforcing their invariants, and therefore the system is sound from an Object-Oriented design perspective.
358 |
359 | However, the capability of a domain entity to enforce local data constraints is only a single property in a set of desirable qualities in a system; while the ADM sacrifices this ability at the granularity of the individual domain entities, it does so in exchange for greater potential `flexibility` and `maintainability` of the overall implementation by allowing the domain logic to be implemented in dedicated classes (and exposed via interfaces).
360 |
361 | ### My personal opinion
362 | Distributing logic all over the place, does not make for a good maintainable product. However, this is very implementation specific.
363 | Using Akka with Persistence, the persistence responsibility is delegated to the Akka runtime and therefor transparant to the implementation.
364 | The Actor handles messages, which makes for better testability, and the best encapsulation / loose coupling I have ever seen in a runtime.
365 | Handling these messages with event handlers can still make for good testable software by modulizing code eg. using facade or services.
366 | Akka makes a Rich Data Model viable and can be used anywhere.
367 |
368 | ## Benefits
369 | * Clear separation between logic and data; (Procedural programming). Each procedure operates on the data.
370 | * Works well for simple applications.
371 | * Results in stateless logic, which facilitates scaling out
372 | * Avoids the need for a complex OO-Database mapping layer.
373 | * It follows the Single Responsibility principle giving a class no more than one reason to change (the data changes).
374 |
375 | ## Liabilities
376 | * Logic __cannot__ be implemented in a truly object-oriented way, because logic and data is separated.
377 | * Violation of the encapsulation and information hiding principles (an object operates upon its state via methods/messages)
378 | * Needs a separate business layer to contain the logic otherwise located in a domain model. It also means that domain model's
379 | objects cannot guarantee their correctness at any moment, because their validation and mutation logic is placed somewhere outside
380 | (most likely in multiple places).
381 | * Needs a service layer when sharing domain logic across differing consumers of an object model (clients of the domain, local
382 | or remote, communicate with the domain by means of a __service__)
383 | * Makes a model less expressive.
384 |
385 | # SOLID Principles of Object Oriented Design
386 | [SOLID principles of Object-Oriented design](https://en.wikipedia.org/wiki/SOLID_(object-oriented_design). The SOLID principles are
387 | guidelines which seek to balance implementation simplicity, scalability, and robustness. Mark Nijhof has written a great book about the SOLID principles, and its available for free so go and get it [SOLID - Software Development is not a Jenga Game - Mark Nijhof](https://leanpub.com/solid).
388 |
389 | The first five principles are principles of class design. They are:
390 | - [Single Reponsibility Principle](https://leanpub.com/solid/read#leanpub-auto-single-responsibility-principle---srp): “A class should have one, and only one, reason to change”. => There should never be more than one reason for a class to change.
391 | - [Open-Closed Principle](https://leanpub.com/solid/read#leanpub-auto-open-closed-principle---ocp): “You should be able to extend a class’s behavior, without modifying it” => Software entities, (classes, modules, functions etc), should be open for extension for closed for modification.
392 | - [Liskov Substitution Principle](https://leanpub.com/solid/read#leanpub-auto-liskov-substitution-principle---lsp): “Derived classes must be substitutable for their base classes.” => Functions that use object references to base classes must be able to use objects of derived classes without knowing it.
393 | - [Interface Segregation Principle](https://leanpub.com/solid/read#leanpub-auto-interface-segregation-principle---isp): “Make fine grained interfaces that are client specific.” => Clients should not be forced to depend upon interfaces that they do not use.
394 | - [Dependency Inversion Principle](https://leanpub.com/solid/read#leanpub-auto-dependency-inversion-principle---dip): “Depend on abstrations, not on concretions.” => A high level module should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions.
395 |
396 | The next six principles are about packages. In this context a package is a binary deliverable like a .jar file, or a dll as
397 | opposed to a namespace like a java package or a C++ namespace.
398 |
399 | The first three package principles are about package cohesion, they tell us what to put inside packages:
400 |
401 | - __REP:__ The Release Reuse Equivalency Principle: The granule of reuse is the granule of release.
402 | - __CCP:__ The Common Closure Principle: Classes that change together are packaged together.
403 | - __CRP:__ The Common Reuse Principle: Classes that are used together are packaged together.
404 |
405 | The last three principles are about the couplings between packages, and talk about metrics that evaluate the
406 | package structure of a system.
407 |
408 | - __ADP:__ The Acyclic Dependencies Principle: The dependency graph of packages must have no cycles.
409 | - __SDP:__ The Stable Dependencies Principle: Depend in the direction of stability.
410 | - __SAP:__ The Stable Abstractions Principle: Abstractness increases with stability.
411 |
412 | ## Manage Dependency
413 | [Dependency Management](http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod) is an issue that most of us have faced.
414 | Whenever we bring up on our screens a nasty batch of tangled legacy code, we are experiencing the results of poor dependency management.
415 | Poor dependency managment leads to code that is hard to change, fragile, and non-reusable. Indeed, I talk about several different design
416 | smells in the PPP book, all relating to dependency management. On the other hand, when dependencies are well managed, the code remains
417 | flexible, robust, and reusable. So dependency management, and therefore these principles, are at the foudation of the -ilities that
418 | software developers desire.
419 |
420 | Solid principles:
421 | - Help manage dependency,
422 | - Improved maintainability, flexibility, robustness, and reusability.
423 |
424 | ## SOLID Resources
425 | - [Bob Martin - SOLID Principles of Object Oriented and Agile Design](https://www.youtube.com/watch?v=TMuno5RZNeE)
426 | - [Robert C Martin - The Single Responsibility Principle](https://www.youtube.com/watch?v=Gt0M_OHKhQE)
427 | - [Robert C. Martin ("Uncle Bob"): Agility and Architecture](https://www.youtube.com/watch?v=0oGpWmS0aYQ)
428 | - [Applying S.O.L.I.D. Principles in Microsoft .NET/C#](https://www.youtube.com/watch?v=Whhi1C2PpaA)
429 |
430 | ## Transaction script pattern
431 | Organizes business logic by procedures where each procedure handles a single request from the presentation.
432 |
433 | Most business applications can be thought of as a series of transactions. A transaction may view some information as
434 | organized in a particular way, another will make changes to it. Each interaction between a client system and a server
435 | system contains a certain amount of logic. In some cases this can be as simple as displaying information in the database.
436 | In others it may involve many steps of validations and calculations.
437 |
438 | A Transaction Script organizes all this logic primarily as a single procedure, making calls directly to the database
439 | or through a thin database wrapper. Each transaction will have its own Transaction Script, although common subtasks can
440 | be broken into subprocedures." In his book "Enterprise Application Patterns", Fowler noted that the transaction script
441 | pattern is OK for many simple business applications, and avoids the need for a complex OO-database mapping layer.
442 |
443 | # Serverless architecture
444 | The word _serverless_ is a bit of a misnomer. Whether you use a compute service such as AWS Lambda to execute your code
445 | or interact with an API, there are still servers running in the background. The difference is that these servers are
446 | hidden from us. There is no infrastructure for us to think about. No way to tweak the underlying operating system.
447 | Someone else takes care of the nitty-gritty detail of infrastructure management, freeing our time for other things.
448 | Serverless is about running code in a compute service and interacting with services and APIs to get the job done.
449 |
450 | There are 5 principles of serverless architecture that describe how an ideal serverless system should be built.
451 | Use these principles to help guide your decisions when you create serverless architecture.
452 |
453 | 1. Use a compute service to execute code on demand (no servers),
454 | 2. Write single-purpose stateless functions (Single Responsibility Principle (SRP)- SOLID design ie. Nano-Compute),
455 | 3. Design push-based, event-driven pipelines,
456 | 4. Create thicker, more powerful front ends,
457 | 5. Embrace third-party services
458 |
459 | There are two notable architectures when going serverless, _compute as back end_ which are back ends for web and mobile applications
460 | and _compute as glue_ which are pipelines built to carry out workflows. These two architectures are complimentary and
461 | it is likely that you will build and combine these architectures if you end up working on any kind of real-world serverless system.
462 |
463 | The _compute-as-back-end_ architecture describes an approach where a serverless compute service such as Lambda and third-party
464 | services are used to build a back end for web, mobile, and desktop applications.
465 |
466 | Good serverless systems try to minimize the scope and the footprint of Lambda functions so that these functions only do
467 | the bare minimum (Nano-Compute) and primarily focus on the tasks that must not be done in the front end due to privacy or security concerns.
468 |
469 | The _compute as glue_ architecture describes the idea that we can use Lambda functions to create powerful execution pipelines
470 | and workflows. This often involves using Lambda as glue between different services, coordinating, and invoking them.
471 | With this style of architecture, the main focus of the developer is on the design of their pipeline, coordination, and flow of data.
472 | The parallelism of serverless compute services like Lambda helps to make these architectures appealing.
473 |
474 | # Nano-Compute
475 | [According to Paul Johnston](https://medium.com/@PaulDJohnston/when-not-to-use-serverless-jeff-6d054d0e7098#.3t6hpwewi),
476 | not all use cases are appropriate for running in a Lambda (Nano Compute). Lets listen to him.
477 |
478 | When using AWS Lambda and similar you are essentially running a nano-container with a single function.
479 | There is a startup cost in terms of time and load, and there is also the fact you don’t know how fast the solution will
480 | run compared with, say, a piece of hardware that you own.
481 |
482 | Once loaded a Lambda will be _warm_ and so will work faster, so that’s ok, but you still don’t have a guarantee of
483 | availability of resources in the same way when you own a server.
484 |
485 | So you have a problem with speed of response, but not reliability or even scalability.
486 |
487 | The whole idea of the single function is the lack of dependencies, which makes it quicker, but doesn’t mean it
488 | necessarily is easier to develop or provide you with an easy way of expanding the function to do more (you might need another function!).
489 |
490 | Basically, the small amount of compute is great for small amounts of load, but for something which is larger, or longer running is probably a little more complex.
491 |
492 | With Lambda, you have __5 minutes maximum__, which is really useful, but the problem is that for a long running task you
493 | have to store data and restart a new function. Basically, split up the task into multiple Lambdas.
494 |
495 | This means that any large scale data task or long running processing task is probably better off a Serverless infrastructure,
496 | or at least, developed in such a way as to be appropriate (which can be done).
497 |
498 | Serverless is primarily an asynchronous solution although it isn’t inherently asynchronous. Therefore you should approach
499 | the majority of tasks as things that you should consume, but not necessarily respond to. So long as you have a mechanism
500 | to respond (push) then the user of an app/mobile/web solution shouldn’t need to worry about anything.
501 |
502 | The exception is when you need real-time (or near real-time) solutions. Under this scenario you have to be confident in
503 | your services and solutions to be fault tolerant but to be honest, the best solution is probably a third party that provides
504 | this for you rather than developing your own serverless nano-compute solution.
505 |
506 | If you need to do something complex with a computer program, then that may not be appropriate. The reference implementation
507 | for a Lambda function is image processing, but imagine it was a video processing function. It might need more memory and
508 | compute than can be garnered from a Lambda compute function, so this might be problematic.
509 |
510 | The problem is amount of available memory and compute, rather than whether the language can handle the complexity itself.
511 | This is a per-function call rather than an architecture call. If you can offload complexities into multiple functions it’s probably fine.
512 |
513 | I would suggest that there are a number of times that Serverless isn’t appropriate:
514 |
515 | - Whenever you need real time that matters at the business level (you can do asynchronous),
516 | - Whenever you need a long running task that can’t be split into multiple compute cycles,
517 | - Whenever you need complex compute with high memory/compute requirements,
518 | - Whenever you need a really good speed of response
519 | - Whenever you need reliability where you can’t guarantee service availability to a high enough level.
520 |
521 | # Serverless Data Processing
522 | A common use for serverless technologies is data processing, conversion, manipulation, and transcoding.
523 | Lambda functions can be used for processing of CSV, JSON, and XML files; collation and aggregation of data;
524 | image resizing; and format conversion. Lambda and AWS services are well suited for building event-driven pipelines
525 | for data-processing tasks: many of them have been designed to integrate and run together
526 | (for example, push a file to an S3 bucket and let a Lambda function run automatically and transform the file).
527 |
528 | Data Processing is an excellent use case for serverless technologies, especially when you use a Lambda function in concert with other services.
529 |
530 | # Serverless Real Time Analytics
531 | Ingestion of data—such as logs, system events, transactions, or user clicks—can be accomplished using services such
532 | as Amazon Kinesis. Lambda functions can react to new records in a stream and process, save, or discard data quickly.
533 | A Lambda function can be configured to run when there is a specific number (batch size) of records available for processing,
534 | so that it doesn’t have to execute for every individual record added to the stream.
535 |
536 | Kinesis streams and Lambda functions are a good fit for applications that generate a lot of data that need to be analyzed,
537 | aggregated, and stored. When it comes to Kinesis, the number of functions spawned to process messages off a stream is the same
538 | as the number of shards (therefore, there is one Lambda function per shard). Furthermore, if a Lambda function fails to process
539 | a batch it will retry again. This can keep going for up to 24 hours (which is how long Kinesis will keep data around before it expires)
540 | if processing fails each time. However, even with these little gotchas, the combination of Kinesis streams and Lambda is powerful if
541 | you want to do real-time processing and analytics.
542 |
543 | # Serverless Legacy API Wrapper
544 | One innovative use case of the AWS API Gateway and Lambda is the legacy API wrapper. Here, developers use API Gateway
545 | and Lambda to create a new API layer over legacy APIs and services to make them easier to use. The API Gateway is used
546 | to create a RESTful interface, and Lambda functions are used to transpose request/response and marshal data to formats
547 | that legacy services can understand. This approach makes legacy services easier to consume for modern clients that
548 | may not support older protocols and data formats.
549 |
550 | # Serverless Scheduled Services
551 | Lambda functions can run on a schedule, which makes them effective for repetitive tasks like data backups, imports and exports,
552 | reminders, and alerts. Lambda functions can be run on a schedule, eg. to periodically ping websites to see if they are online
553 | and send an email or a text message if they are not. There are Lambda blueprints available for this specific use case.
554 | A blueprint is a template with sample code that can be selected when creating a new Lambda function.
555 |
556 | Lambda functions can also be scheduled to perform nightly downloads of files off servers and send daily account statements to users.
557 | Repetitive tasks such as file backup and file validation can also be done easily with Lambda thanks to the scheduling capability that
558 | you can set and forget.
559 |
560 | # AWS Lambda
561 | [AWS Lambda](http://docs.aws.amazon.com/lambda/latest/dg/welcome.html) is a compute service that executes code written
562 | in JavaScript [node.js](https://nodejs.org/en/), [Python](https://www.python.org/downloads/), Java or Scala on AWS infrastructure.
563 |
564 | Source code is deployed to an isolated container that has its own allocation of memory, disk space, and CPU.
565 | The combination of your code, configuration and depedencies, is typically referred to as a Lambda function.
566 |
567 | The Lambda runtime can invoke a function multiple times in parallel. Lambda supports push and pull event models of
568 | operation and integrates with a large number of AWS services. Functions can be invoked by an HTTP request
569 | through the [AWS API Gateway](https://aws.amazon.com/api-gateway/), or run on a scheduler.
570 |
571 | AWS is not the only vendor that provides a lambda architecture runtime. [Microsoft Azure Functions](https://azure.microsoft.com/nl-nl/services/functions/),
572 | [IBM Bluemix OpenWhisk](http://www.ibm.com/cloud-computing/bluemix/openwhisk/), and [Google Cloud Functions](https://cloud.google.com/functions/docs/)
573 | are other providers of lambda architecture runtimes (which may or may not be inter-compatible).
574 |
575 | # AWS API Gateway
576 | [AWS API Gateway](https://aws.amazon.com/api-gateway/) is a service that you can use to create an API layer between the front end and back end services.
577 | The lifecycle management of the API Gateway allows multiple versions of the API to be run at the same time and it supports multiple release stages
578 | such as development, staging, and production. API Gateway also comes with useful features like caching and throttling of requests.
579 |
580 | # AWS Simple Notification Service (SNS)
581 | [AWS Simple Notification Service (SNS)](https://aws.amazon.com/sns/) is a scalable pub-sub service designed to deliver messages.
582 | Producers or publishers create and send messages to a topic. Subscribers or consumers subscribe to a topic and receive messages
583 | over one of the supported protocols. SNS stores messages across multiple servers and data centers for redundancy and guarantees
584 | __at-least-once delivery__. At-least-once delivery stipulates that a message will be delivered at least once to a subscriber but,
585 | on a rare occasion due to the distributed nature of SNS, it may be delivered multiple times.
586 |
587 | At least once means that a message can be received multiple times which also means that your lambda must handle processing
588 | the same message multiple times, implying idempotency.
589 |
590 | In cases when messages cannot be delivered by SNS to HTTP endpoints, it can be configured to retry deliveries at a later time.
591 | SNS can also retry failed deliveries to Lambda in cases where throttling is applied. SNS supports message payloads of up to 256KB.
592 |
593 | # AWS Simple Storage Service (S3)
594 | [AWS Simple Storage Service (S3)](https://aws.amazon.com/documentation/s3/) is Amazon’s scalable storage solution.
595 | Data in S3 is stored redundantly across multiple facilities and servers. The event notifications system allows S3 to
596 | send events to SNS, SQS, or Lambda when objects are created or deleted. S3 is secure by default, with only owners having
597 | access to the resources they create; however, it is possible to set more granular and flexible access permissions using
598 | Access Control Lists (ACL) and bucket policies.
599 |
600 | S3 uses the concept of buckets and objects. Buckets are high-level directories or containers for objects. Objects are a
601 | combination of data, metadata, and a key. A key is a unique identifier for an object in a bucket. S3 also supports the
602 | concept of a folder as a means of grouping objects in the S3 console. Folders work by using key name prefixes.
603 | A forward slash character “/” in the key name delineates a folder. For example, an object with a key name documents/personal/myfile.txt
604 | is represented as a folder called documents containing a folder called personal containing the file myfile.txt in the S3 console.
605 |
606 | # AWS Simple Queue Service (SQS)
607 | [AWS Simple Queue Service (SQS)](https://aws.amazon.com/documentation/sqs/) is Amazon’s distributed and fault-tolerant queuing service.
608 | It ensures __at-least-once delivery__ of messages similar to SNS and supports message payloads of up to 256KB. SQS allows multiple
609 | publishers and consumers to interact with the same queue, and it has a built-in message lifecycle that automatically expires and deletes
610 | messages after a preset retention period. As with most AWS products, there are access controls to help control access to the queue.
611 | SQS integrates with SNS to automatically receive and queue messages.
612 |
613 | # AWS Simple Email Service (SES)
614 | [AWS Simple Email Service (SES)](https://aws.amazon.com/documentation/ses/) is a service designed to send and receive email.
615 | SES handles email-receiving operations such as scanning for spam and viruses, and rejection of email from untrusted sources.
616 | Incoming email can be delivered to an S3 bucket, used to invoke a Lambda notification, or create an SNS notification.
617 | These actions can be configured as part of the receipt rule, which tells SES what to do with the email once it arrives.
618 |
619 | Sending emails with SES is straightforward but there are limits, which are in place to regulate the rate and the number
620 | of messages being sent out. SES will automatically increase the quota as long as high-quality email, and not spam, is being sent.
621 |
622 | # AWS Relational Database Service (RDS)
623 | [AWS Relational Database Service (RDS)](https://aws.amazon.com/documentation/rds/) is a web service that helps with the set up
624 | and operation of a relational database in the AWS infrastructure. RDS supports Amazon Aurora, MySQL, MariaDB, Oracle, MS-SQL,
625 | and PostgreSQL database engines. It takes care of routine tasks such as provisioning, backup, patching, recovery, repair, and failure detection.
626 | Monitoring and metrics, database snapshots, and multiple Availability Zone (AZ) support are provided out of the box. RDS uses SNS to deliver
627 | notifications when an event occurs. This makes it easy to respond to database events such as creation, deletion, failover, recovery, and restoration when they happen.
628 |
629 | # AWS DynamoDB
630 | [AWS DynamoDB](https://aws.amazon.com/documentation/dynamodb/) is Amazon’s NoSQL solution. Tables, items, and attributes are Dynamo’s main concepts.
631 | A table stores a collection of items. An item is made up of a collection of attributes. Each attribute is a simple piece of data such as a person’s
632 | name or phone number. Every item is uniquely identifiable. Lambda integrates with DynamoDB tables and can be triggered by a table update.
633 |
634 | # AWS CloudSearch
635 | [AWS CloudSearch](https://aws.amazon.com/documentation/cloudsearch/) is a search solution from AWS that supports structured data and plain text.
636 | CloudSearch takes snippets of data as JSON or XML and generates an index that can be queried. This service supports boolean, prefix, and range searches,
637 | full-text search, faceting, highlighting, and auto-complete. Every document provided to CloudSearch is supplied with an ID, generated by the user,
638 | that makes the document uniquely identifiable. Search requests can be carried out using GET requests. Results can be returned as JSON or XML,
639 | and they can be sorted, paginated, and include useful metadata such as a relevance score.
640 |
641 | # AWS CloudFront
642 | [AWS CloudFront](https://aws.amazon.com/documentation/cloudfront/) is a web service that speeds up distribution of your
643 | static and dynamic web content, for example, .html, .css, .php, image, and media files, to end users.
644 |
645 | # AWS Route 53
646 | [AWS Route 53](https://aws.amazon.com/documentation/route53/) is a highly available and scalable Domain Name System (DNS) web service.
647 |
648 | # AWS Virtual Private Cloud (VPC)
649 | [AWS Virtual Private Cloud (Amazon VPC)](https://aws.amazon.com/documentation/vpc/) enables you to launch Amazon Web Services (AWS)
650 | resources into a virtual network that you've defined. This virtual network closely resembles a traditional network that you'd operate
651 | in your own data center, with the benefits of using the scalable infrastructure of AWS.
652 |
653 | # AWS Elastic Transcoder
654 | [AWS Elastic Transcoder](https://aws.amazon.com/documentation/elastic-transcoder/) is an AWS service for transcoding media to other formats,
655 | resolutions, and bitrates. This service is useful if you need to have versions of your media playable on different devices. Elastic Transcoder
656 | comes with a number of presets or templates that define how a video should be transcoded, but you can define your own.
657 |
658 | It integrates with S3 and SNS, which it uses for notifications when a job is completed or an error condition is raised.
659 | Elastic Transcoder also has additional features such as watermarking, transcoding of captions, and DRM support.
660 |
661 | # AWS Kinesis
662 | [AWS Kinesis](https://aws.amazon.com/documentation/kinesis/) is a service for real-time processing of streaming big data.
663 | It is typically used for quick log and data intake, metrics, analytics, and reporting. It is different from SQS in that
664 | Amazon recommends that Kinesis Streams be used primarily for streaming big data, whereas SQS is used as a reliable hosted
665 | queue especially if more fine-grained control over messages, such as visibility timeouts or individual delays, is required.
666 |
667 | In AWS Kinesis, shards specify the throughput capacity of a stream. The number of shards needs to be stipulated when the
668 | stream is created; however, resharding is possible if throughput needs to be increased or reduced. In comparison, SQS makes
669 | scaling much more transparent. Lambda can integrate with Kinesis to read batches of records from a stream as soon as they are detected.
670 |
671 | # AWS Internet of Things (IoT)
672 | [AWS IoT](https://aws.amazon.com/documentation/iot/) enables secure, bi-directional communication between Internet-connected
673 | things (such as sensors, actuators, embedded devices, or smart appliances) and the AWS cloud over [MQTT](http://mqtt.org/) and HTTP.
674 |
675 | AWS IoT combines the following:
676 |
677 | - authentication and authorization,
678 | - communications gateway,
679 | - registry (a way to assign a unique identity to each device),
680 | - device shadowing (persistent device state),
681 | - a rules engine (a service to transform and route device messages to AWS services).
682 |
683 | The rules engine, for example, can save files to Amazon’s Simple Storage Service (S3), push data to an Amazon Simple Queue Service (SQS) queue, and invoke AWS Lambda
684 | functions. Amazon’s IoT platform makes it easy to build scalable IoT back ends for devices without having to run a server.
685 |
686 | # AWS Cognito
687 | [AWS Cognito](https://aws.amazon.com/documentation/cognito/) is an identity management service. It integrates with public
688 | identity providers such as Google, Facebook, Twitter, and Amazon, or with your own system. Cognito supports synchronization
689 | of user application data across different devices and has offline support that allows mobile devices to function even when there
690 | is no Internet access.
691 |
692 | # Auth0
693 | [Auth0](https://auth0.com/) is a non-AWS identity management product that has a few features that Cognito doesn’t.
694 | Auth0 integrates with more than 30 identity providers, including Google, Facebook, Twitter, Amazon, LinkedIn, and Windows Live.
695 | It provides a way to register new users, through the use of its own user database, without having to integrate with an identity provider.
696 | In addition, it has a facility to import users from other databases.
697 |
698 | As expected, Auth0 supports standard industry protocols including SAML, OpenID Connect, OAuth 2.0, OAuth 1.0, and JSON Web Tokens.
699 | It is dead simple to integrate with AWS Identity & Access Management, and with Cognito.
700 |
701 | # GraphQL
702 | [GraphQL](http://graphql.org/) is a popular data query language developed by Facebook in 2012 and released publicly in 2015.
703 | It was designed as an alternative to REST (Representational State Transfer) due to REST’s perceived weaknesses
704 | (multiple round-trips, over-fetching, and problems with versioning). GraphQL attempts to solve these problems by providing a
705 | hierarchical, declarative way of performing queries from a single end point.
706 |
707 | GraphQL gives power to the client. Instead of specifying the structure of the response on the server, it is defined on the client.
708 | The client can specify what properties and relationships to return. GraphQL aggregates data from multiple sources and returns it to the
709 | client in a single round trip (which makes it an efficient system for retrieving data). According to Facebook, GraphQL serves millions
710 | of requests per second from nearly 1000 different versions of their application.
711 |
712 | In serverless architectures, GraphQL is usually hosted and run from a single Lambda function which can be connected to an API Gateway
713 | GraphQL can query and write to multiple data sources (such as DynamoDB tables) and assemble a response that matches the request.
714 | A serverless GraphQL is a rather interesting approach you might want to look at the next time you need to design an interface for your API and query data.
715 |
716 | There is a [reference implementation available on Github](https://github.com/graphql/graphql-js/) which is implemented in JavaScript _GraphQL.js_.
717 |
718 | There is only one viable GraphQL implementation for Scala available: [Sangria](http://sangria-graphql.org/).
719 |
720 | For a list of GraphQL implementations see [Awesome GraphQl overview by C. T. Lin](https://github.com/chentsulin/awesome-graphql#lib-scala).
721 |
722 | # Reactive Design Patterns
723 |
724 | ## Video's
725 | * [Youtube - Stuart Sierra - Functional Design Patterns](https://www.youtube.com/watch?v=etr08mExAI0)
726 |
727 | # Links
728 | * [Design Pattern in Simple Examples](http://www.go4expert.com/articles/design-pattern-simple-examples-t5127)
729 | * [Scala Best Practices](https://github.com/alexandru/scala-best-practices)
730 |
731 | # TypeTags
732 | A [TypeTag](http://www.scala-lang.org/api/2.11.7/scala-reflect/#scala.reflect.api.TypeTags) encapsulates the runtime
733 | type representation of some type `T`. The prime use case of `TypeTag`s is to give access to erased types.
734 |
735 | There are three different [TypeTags](http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html):
736 |
737 | - scala.reflect.api.TypeTags#TypeTag: A full type descriptor of a Scala type. For example, a TypeTag[List[String]] contains all type information, in this case, of type scala.List[String].
738 | - scala.reflect.ClassTag: A partial type descriptor of a Scala type. For example, a ClassTag[List[String]] contains only the erased class type information, in this case, of type scala.collection.immutable.List. ClassTags provide access only to the runtime class of a type. Analogous to scala.reflect.ClassManifest
739 | * [StackOverflow - Scala: What is a TypeTag and how do I use it?](http://stackoverflow.com/questions/12218641/scala-what-is-a-typetag-and-how-do-i-use-it)
740 |
741 | # Functional Programming
742 | - [Youtube - Robert C Martin - Functional Programming; What? Why? When?](https://www.youtube.com/watch?v=7Zlp9rKHGD4)
743 | - [Youtube - Robert C Martin - Clean Architecture and Design](https://www.youtube.com/watch?v=Nsjsiz2A9mg)
744 | - [Youtube - Robert C. Martin - The Land that Scrum Forgot](https://www.youtube.com/watch?v=hG4LH6P8Syk)
745 |
746 | ## Software Architecture
747 | The software architecture of a computing system is the set of structures needed to reason about the system, which comprise software elements, relations among them, and properties of both.
748 |
749 | Software architecture has emerged as an important subdiscipline of software engineering. Architecture is roughly the prudent partitioning of a whole into parts, with specific relations among the parts. This partitioning is what allows groups of people—often separated by organizational, geographical, and even time-zone boundaries—to work cooperatively and productively together to solve a much larger problem than any of them could solve individually.
750 |
751 | Each group writes software that interacts with the other groups’ software through carefully crafted interfaces that reveal the minimal and most stable information necessary for interaction. From that interaction emerges the functionality and quality attributes—security, modifiability, performance, and so forth—that the system’s stakeholders demand. The larger and more complex the system, the more critical is this partitioning—and hence, architecture. The more demanding those quality attributes are, the more critical the architecture is.
752 |
753 | A single system is almost inevitably partitioned simultaneously in a number of different ways. Each partitioning results in the creation of an architectural structure: different sets of parts and different relations among the parts. Each is the result of careful design, carried out to satisfy the driving quality attribute requirements and the most important business goals behind the system.
754 |
755 | Many projects make the mistake of trying to impose a single partition in multiple component domains, such as equating threads with objects, which are equated with modules, which in turn are equated with files. Such an approach never succeeds fully, and adjustments eventually must be made, but the damage of the initial intent is often hard to repair.
756 |
757 | This invariably leads to problems in development and occasionally in final products. Architecture is what makes the sets of parts work together as a coherent and successful whole. Architecture documentation help architects make the right decisions; it tells developers how to carry them out; and it records those decisions to give a system’s future caretakers insight into the architect’s solution.
758 |
759 | For nearly all systems, quality attributes such as 'performance', 'reliability', 'security', and 'modifiability' are every bit as important as making sure that the software computes the correct answer. A software system’s ability to produce correct results isn’t helpful if it takes too long doing it, or the system doesn’t stay up long enough to deliver it, or the system reveals the results to your competition or your enemy. Architecture is where these concerns are addressed. For example:
760 |
761 | - If you require high __performance__, you need to:
762 | - Exploit potential parallelism by decomposing the work into cooperating or synchronizing processes.
763 | - Manage the interprocess and network communication volume and data access frequencies.
764 | - Be able to estimate expected latencies and throughputs.
765 | - Identify potential performance bottlenecks.
766 | - If your system needs high __accuracy__, you must pay attention to how the data elements are defined and used and how their values flow throughout the system.
767 | - If __security__ is important, you need to:
768 | - Legislate usage relationships and communication restrictions among the parts.
769 | - Identify parts of the system where an unauthorized intrusion will do the most damage.
770 | - Possibly introduce special elements that have earned a high degree of trust.
771 | - If you need to support __modifiability__ and portability, you must carefully separate concerns among the parts of the system, so that when a change affects one element, that change does not ripple across the system.
772 | - If you want to __deploy the system incrementally__, by releasing successively larger subsets, you have to keep the dependency relationships among the pieces untangled, to avoid the 'nothing works until everything works' syndrome.
773 |
774 | The solutions to these concerns are purely architectural in nature. It is up to architects to __find those solutions__ and __communicate them__ effectively to those who will carry them out. Architecture documentation has three obligations related to quality attributes:
775 |
776 | 1. First, it should indicate which quality attribute requirements drove the design.
777 | 2. Second, it should capture the solutions chosen to satisfy the quality attribute requirements.
778 | 3. Finally, it should capture a convincing argument why the solutions provide the necessary quality attributes. The goal is to capture enough information so that the architecture can be analyzed to see if, in fact, the system(s) derived from it will possess the necessary quality attributes.
779 |
780 | ## What is Software Architecture?
781 | If we are to agree on what it means to document a software architecture, we should establish a common basis for what it is we’re documenting. No universal definition of software architecture exists. The Software Engineering Institute’s Web site collects definitions from the literature and from practitioners around the world; so far, more than 150 definitions have been collected. It seems that new fields try to nail down standard definitions or their key terms as soon as they can. As the field matures, basic concepts become more important than ironclad definitions, and this urge seems to fade.
782 |
783 | When object-oriented development was in its infancy, you could bring any OO meeting to a screeching halt by putting on your best innocent face and asking, “What exactly is an object?” This largely ended when people realized that the scatter plot of definitions had an apparent (if unarticulated) centroid, from which very useful progress could be made. Sometimes “close enough” is, well, close enough.
784 |
785 | This seems to be the case with software architecture. Looking at the major attempts to nail down its definition gives us a good glimpse at our own centroid. That centroid takes a largely structural perspective on software architecture:
786 |
787 | _Software architecture is composed of elements, connections or relations among them, and, usually, some other aspect or aspects, such as (take your pick) configuration; constraints or semantics; analyses or properties; or rationale, requirements, or stakeholders’ needs._
788 |
789 | These perspectives do not preclude one another, nor do they represent a fundamental conflict about what software architecture is. Instead, they represent a spectrum in the software architecture community about the emphasis that should be placed on architecture: its constituent parts, the whole entity, the way it behaves once built, or the building of it. Taken together, they form a consensus view of software architecture.
790 |
791 | So we end up with the following definition:
792 |
793 | _The software architecture of a program or computing system is the structure or structures of the system, which comprise software elements, the externally visible properties of those elements, and the relations among them. By 'externally visible properties,'' we are referring to those assumptions other components can make of a component, such as its provided services, performance characteristics, fault handling, shared resource usage, and so on.
794 |
795 | The previous definition of software architecture fits the goal of knowing what to document about an architecture and thus coming up with a Software Architecture Document (SAD) that is usable by multiple stakeholders. The definition emphasizes the plurality of structures present in every software system. These structures, carefully chosen and designed by the architect, are the key to achieving and reasoning about the system’s design goals. And those structures are the key to understanding the architecture. Therefore, they are the focus of the approach to documenting a software architecture. __Structures consist of elements, relations among the elements, and the important properties of both. So documenting a structure entails documenting those things__.
796 |
797 | ## What’s the Difference Between Architecture and Design?
798 | The question of how architecture is different from design has nipped at the heels of the software development community for years. It is a question I often hear when teaching an introductory course on architecture. It matters here because the question deals with what we should put in an architecture document and what we should put somewhere else.
799 |
800 | The first thing we can say is that __clearly architecture is design__, _but not all design is architecture_. That is, many design decisions are left unbound by the architecture and are happily left to the discretion and good judgment of downstream designers and even implementers. The architecture establishes constraints on downstream activities, and those activities must produce artifacts—finer-grained designs and code—that comply with the architecture.
801 |
802 | It’s tempting to stop there, but if you’re paying attention you’ve seen that we’ve just translated the question: Architecture consists of _architectural design decisions_, and all others are _nonarchitectural_. So what decisions are nonarchitectural? That is, what design decisions does the architect leave to the discretion of others? To answer this question, we return to the primary purpose of architecture, which is to assure the satisfaction of the system’s quality and behavioral requirements and business goals. The architect does this by making design decisions that manifest themselves in the system’s architectural structures. Thus, architectural decisions are ones that permit a system to meet its quality attribute and behavioral requirements. All other decisions are nonarchitectural.
803 |
804 | Clearly any design decisions resulting in element properties that are not visible — that is, make no difference outside the element — are nonarchitectural. A typical example is the selection of a data structure, along with the algorithms to manage and access that data structure.
805 |
806 | You may have been hoping for a more concrete answer, such as 'the first three levels of module decomposition are architectural, but any subsequent decomposition is not.' Or, 'the classes, packages and their relations in a UML class diagram are architectural, but sequence diagrams are not.' Or 'defining the services of an SOA system is architectural, but designing the internal structure of each service provider component is not.'
807 |
808 | But those don’t work because they draw arbitrary and artificial boundaries. Attempts like that to be practical end up being impractical because true architecture bleeds across those boundaries.
809 |
810 | Here are some more sometimes-heard artificial definitions:
811 |
812 | 1. First, 'architecture is the small set of big design decisions.' Some people define 'small set' by insisting that an architecture document should be no more than 50 pages. Or 80. Or 30. Their feeling, apparently, is that architecture is the set of design decisions that you can squeeze into a given page quota, and everything beyond that is not. This is, of course, utter nonsense.
813 | 2. Another oft-heard nonanswer is 'architecture is what you get before you start adding detail to the design.' Terminology often directs our thinking, rather than serves it. A pernicious example that puts us in the wrong mind set is 'detailed design.' Detailed design is what many people say follows architecture. The term is everywhere, and needs to be stamped out. It implies that the difference between architectural and nonarchitectural design is something called 'detail.' Architecture is apparently not allowed to be detailed, because if it is, well, you’re doing detailed design then, aren’t you? Never mind that we have no idea how to measure 'detail' nor to set a threshold for when there is too much of it to be architectural. If your design starts to look 'detailed' then you aren’t doing architecture and you’ll be reported to the Detailed Design Police for overstepping your authority. More utter nonsense.
814 |
815 | It’s true that some architectural design decisions may lack much specificity; that is, they preserve freedom of choice for downstream designers. Some architectural design decisions may not be 'decisions' at all, but broad constraints. Plug-ins that populate your Web browser are an example. No architecture nails down the complete set, but the architecture does constrain new ones to meet certain standards and interfaces. Or the architect might describe an element by saying, 'The element delivers its computational result through this published interface, is thread-safe, puts no more than three messages on the network per invocation, and returns its answer in less than 20 ms.' The team implementing that element is free to make whatever design decisions they wish as long as they satisfy the architect’s architect’s prescription for it.
816 |
817 | On the other hand, some architectural decisions can be quite 'detailed,' such as the adoption of specific protocols, an XML schema, or communication or technology standards. Such decisions are usually made for purposes of interoperability or various flavors of modifiability (such as scalability or extensibility).
818 |
819 | Even interfaces of elements, which some decry as 'obviously' outside the realm of architecture, can be supremely architectural. For instance, in a service-oriented architecture (SOA), components interact through published interfaces. Important design decisions made when defining these interfaces include the granularity of the operations, the data format, and the type of interaction (synchronous or asynchronous) for each operation. Or consider an element that processes data from a real-time sensor. Making this element’s interface process a stream as opposed to individual data elements will make an enormous difference in the ability of the element (and hence the system) to meet real-time performance requirements. This decision cannot be left up to the element’s development team; everything depends on it.
820 |
821 | A legitimate question about detail does arise when considering modules and other hierarchical elements (A hierarchical element is any kind of element that can consist of like-kind elements. A module is a hierarchical element because modules consist of submodules, which are themselves modules. A task or a process is not a hierarchical element).
822 |
823 | When do you stop? When have you designed enough levels in the hierarchy? Are submodules enough, or does the architect need to design sub-sub-sub-submodules? Here’s a good test of our claim for when architecture stops. Module decomposition is about achieving independent development and modifiability. Both are achieved by carefully assigning coherent responsibilities to each module. When the modules you’ve designed are fine-grained enough to satisfy the system’s modifiability and independent development requirements, you’ve discharged your obligation as an architect.
824 |
825 | Finally, what is architectural is sensitive to context. Suppose the architect identifies an element but is content to sketch the element’s interface and behavior in broad terms. If the element being prescribed is very large and complex, the team developing it may choose to give it an internal substructure of its own, which for all the world looks like an architecture. And within the context of that element, it is. But in the context of the overall system, the substructure is not architectural but merely an internal design decision made by the development team for that element.
826 |
827 | To summarize, architecture is design, but not all design is architectural. The architect draws the boundary between architectural and nonarchitectural design by making those decisions that need to be bound in order for the system to meet its development, behavioral, and quality goals. All other decisions can be left to downstream designers and implementers. Decisions are architectural or not, according to context. If structure is important to achieve your system’s goals, that structure is architectural. But designers of elements, or subsystems, that you assign may have to introduce structure of their own to meet their goals, in which case such structures are architectural: to them but not to you.
828 |
829 | # Books
830 | - [Documenting Software Architectures - Views and Beyond - Paul Clements et al](https://www.amazon.com/Documenting-Software-Architectures-Views-Beyond/dp/0321552687)
831 | * [Software Architecture For Developers](https://leanpub.com/software-architecture-for-developers) - [Simon Brown](https://twitter.com/simonbrown) (2016)
832 |
833 | # My notes on Software Architecture for Developers
834 | The book [Software Architecture for Developers](https://leanpub.com/software-architecture-for-developers) is great!
835 | It demystifies Software Architecture by continuously asking questions and where appropriate putting definitions in
836 | place when no clear answer could be found based on common sense. Simon Brown did a great job clearing the fog of war that exists in
837 | software development. It is a must read for everyone creating software. Now let's give [Simon Brown](https://twitter.com/simonbrown) a lot of money,
838 | buy the book and go read!
839 |
840 | Below are my notes and excerpt from the book:
841 |
842 | ## What is software architecture?
843 |
844 | * The software architect is a role, preferably shared and fulfilled by the whole development team, if possible,
845 | * When the architect's role is fulfilled by a single person, the approach should be `coding`, `coaching` and `collaborative design`,
846 | * Software architecture is about `structure` and `vision`,
847 | * Software architecture is about `the high-level structure` of a `software system` and how one gets to an `understanding` of it,
848 | * Software architecture is about `the significant decisions` that `influence the shape` of a software system,
849 | * Software architecture is about `the things that are hard or expensive to change`,
850 | * When a team does not consider software architecture, bad things tend to happen; one could end up with a poorly structured, internal inconsistent software system that are hard to understand, hard to maintain and potentially don't satisfy one or more of the important non-functional requirements such as performance, scalability or security.
851 | * One should explicitly think about software architecture, it provides a way to introduce technical leadership and stack the odds of a successful delivery in your favor,
852 | * Software architecture is `not` about `big design up front`,
853 |
854 | # My notes on The Art of Visualizing Software Architecture
855 | The book [The Art of Visualizing Software Architecture](https://leanpub.com/visualising-software-architecture) teaches a method how to visually
856 | communicate the software architecture which is the static structure of a software system. Below are my notes and excerpt from the book:
857 |
858 | ## Shared Vocabulary
859 | First of all, it is very important to share the vocabulary that you will be using in the diagrams. We will be using the vocabulary that
860 | consists of `containers`, `components` and `classes/code`. With this shared vocabulary we can draw diagrams at varying levels of abstraction.
861 |
862 | * A software system is a hierarchy of simple building blocks,
863 | * A software system is made up of one or more `containers` each of which contains one or more `components` which in turn are implemented by one or more `classes`,
864 | * A `container` can be a web applications, mobile apps, standalone applications, databases, file systems, Microservice, shell script, etc,
865 | * A `component` is a grouping or `related functionality` encapsulated behind a well defined `interface`,
866 | * A `component` will be implemented by one or more `classes` so a component contains one or more classes,
867 | * In OO: a component is made up of classes and interfaces,
868 | * In FP: A component could be a module which is a logical grouping of related functions, types, etc,
869 | * In JS: A component could be a JavaScript module, which is made up of a number of objects and functions,
870 | * In a RDBMS: A component could be a logical grouping of functionality; based upon a number of tables, views, stored procedures, functions, triggers, etc,
871 |
872 | 
873 |
874 | ## The Context Diagram - People and Software Systems
875 | The `context diagram` is useful to get the big picture. It does not show much detail but it does help to set the scene and
876 | is a starting point for other diagrams. The diagram should show how a software system fits in to the overall environment.
877 | All software systems `should have` a context diagram. The context diagram is usually the starting point for diagramming and
878 | documenting a software system.
879 |
880 | The context diagram is often drawn during a requirements gathering workshop, to ensure that everybody understands the scope of
881 | what will be build. The focus should be on `people` (actors, roles, personas, etc) and `software systems` rather than technologies,
882 | protocols and other low-level details. It is the diagram that you would show non-technical people.
883 | The diagram should show `people` and `software systems`.
884 |
885 | The context diagram helps to answer the questions:
886 |
887 | - What is the software system that we are building?
888 | - Who is using it?
889 | - How does it fit in with the existing environment?
890 |
891 | The context diagram shows the following:
892 |
893 | * It makes the context and scope explicit, so that there are no assumptions,
894 | * It shows what is being added to an existing environment,
895 | * It is a high-level diagram that technical and non-technical people can use as a starting point for discussions,
896 | * It provides a starting point for identifying who you potentially need to go and talk to as far as understanding inter-system interfaces is concerned.
897 |
898 | 
899 |
900 | ## The Container Diagram - High Level Technology Choices
901 | The `container diagram` illustrates the high-level technology choices. It shows the high-level shape of the software architecture
902 | (the static structure) and how responsibilities are distributed across it. It shows the major technology choices and how the containers
903 | communicate with each other. It is a simple `technology-focused` diagram that is useful for `software developers` and `support/operations staff`.
904 |
905 | The container diagram helps answer the questions:
906 |
907 | - What is the overal shape of the software system?
908 | - What are the high-level technology decisions?
909 | - How are responsibilities distributed across the system?
910 | - How do containers communicate with each other?
911 | - As a developer, where do I need to write code in order to implement features?
912 |
913 | 
914 |
915 | ## CAP theorem
916 | In theoretical computer science, the [CAP theorem](https://en.wikipedia.org/wiki/CAP_theorem), also named Brewer's theorem
917 | after computer scientist Eric Brewer, states that it is impossible for a __distributed computer system__ to _simultaneously_ provide
918 | all three of the following guarantees:
919 |
920 | 1: __Consistency:__ Every read receives the most recent write or an error
921 | 2: __Availability:__ Every request receives a response, without guarantee that it contains the most recent version of the information
922 | 3: __Partition tolerance:__ The system continues to operate despite an arbitrary number of messages being dropped by the network between nodes
923 |
924 | No distributed system is safe from network failures, thus network partitioning generally has to be tolerated. In the presence of a
925 | partition, one is then left with two options: consistency or availability.
926 |
927 | __Choosing consistency over availability:__
928 | When choosing consistency over availability, the system will return an error or a time out if particular information cannot be
929 | guaranteed to be up to date due to network partitioning.
930 |
931 | __Choosing availability over consistency:__
932 | When choosing availability over consistency, the system will always process the query and try to return the most recent available
933 | version of the information, even if it cannot guarantee it is up to date due to network partitioning.
934 |
935 | In the absence of network failure, that is, when the distributed system is running normally, both availability and consistency
936 | can be satisfied (in case of some database systems, a consistency level can be requested with a query).
937 |
938 | CAP is frequently misunderstood as if one had to choose to abandon one of the three guarantees at all times. In fact,
939 | the choice is really between consistency and availability for when a partition happens only; at all other times,
940 | no trade-off has to be made.
941 |
942 | Database systems designed with traditional [ACID](https://en.wikipedia.org/wiki/ACID) (Atomicity, Consistency, Isolation, Durability) guarantees in mind such as RDBMS
943 | choose consistency over availability, whereas systems designed around the [BASE](https://en.wikipedia.org/wiki/Eventual_consistency)
944 | philosophy (Eventual Consistency), common in the NoSQL movement for example, choose availability over consistency.
945 |
946 | The [PACELC](https://en.wikipedia.org/wiki/PACELC_theorem) theorem builds on CAP by stating that even in the absence of
947 | partitioning, another trade-off between latency and consistency occurs.
948 |
949 | ## PACELC theorem
950 | In theoretical computer science, the [PACELC](https://en.wikipedia.org/wiki/PACELC_theorem) theorem is an extension to the
951 | [CAP theorem](https://en.wikipedia.org/wiki/CAP_theorem). It states that in case of network partitioning (P)
952 | in a distributed computer system, one has to choose between availability (A) and consistency (C) (as per the CAP theorem),
953 | but else (E), even when the system is running normally in the absence of partitions, one has to choose between latency (L)
954 | and consistency (C).
955 |
956 | PACELC builds on the CAP theorem. Both theorems describe how distributed databases have limitations and tradeoffs regarding
957 | consistency, availability, and partition tolerance. PACELC however goes further and states that a trade-off also exists,
958 | this time between latency and consistency, even in absence of partitions, thus providing a more complete portray of the
959 | potential consistency tradeoffs for distributed systems.
960 |
961 | A high availability requirement implies that the system must replicate data. As soon as a distributed system replicates data,
962 | a tradeoff between consistency and latency arises.
963 |
--------------------------------------------------------------------------------
/build.sbt:
--------------------------------------------------------------------------------
1 | name := "design-patterns-study"
2 |
3 | version := "1.0"
4 |
5 | scalaVersion := "2.11.8"
6 |
7 | libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.1" % Test
8 |
9 | licenses += ("Apache-2.0", url("http://opensource.org/licenses/apache2.0.php"))
10 |
11 | // enable scala code formatting //
12 | import scalariform.formatter.preferences._
13 |
14 | scalariformSettings
15 |
16 | ScalariformKeys.preferences := ScalariformKeys.preferences.value
17 | .setPreference(AlignSingleLineCaseStatements, true)
18 | .setPreference(AlignSingleLineCaseStatements.MaxArrowIndent, 100)
19 | .setPreference(DoubleIndentClassDeclaration, true)
20 |
21 | // enable updating file headers //
22 | import de.heikoseeberger.sbtheader.license.Apache2_0
23 |
24 | headers := Map(
25 | "scala" -> Apache2_0("2015", "Dennis Vriend"),
26 | "conf" -> Apache2_0("2015", "Dennis Vriend", "#")
27 | )
28 |
29 | enablePlugins(AutomateHeaderPlugin)
--------------------------------------------------------------------------------
/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=0.13.9
2 |
--------------------------------------------------------------------------------
/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | resolvers += "sonatype-releases" at "https://oss.sonatype.org/content/repositories/releases/"
2 |
3 | resolvers += "bintray-sbt-plugin-releases" at "http://dl.bintray.com/content/sbt/sbt-plugin-releases"
4 |
5 | // to format scala source code
6 | addSbtPlugin("com.typesafe.sbt" % "sbt-scalariform" % "1.3.0")
7 |
8 | // enable updating file headers eg. for copyright
9 | addSbtPlugin("de.heikoseeberger" % "sbt-header" % "1.5.0")
--------------------------------------------------------------------------------
/src/test/scala/com/github/dnvriend/TestSpec.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Dennis Vriend
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.github.dnvriend
18 |
19 | import org.scalatest.{ GivenWhenThen, FlatSpec, Matchers }
20 |
21 | class TestSpec extends FlatSpec with Matchers with GivenWhenThen
22 |
--------------------------------------------------------------------------------
/src/test/scala/com/github/dnvriend/oo/behavioral/CommandPatternTest.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Dennis Vriend
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.github.dnvriend.oo.behavioral
18 |
19 | import com.github.dnvriend.TestSpec
20 |
21 | class CommandPatternTest extends TestSpec {
22 | "" should "" in {
23 |
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/test/scala/com/github/dnvriend/oo/behavioral/IteratorPatternTest.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Dennis Vriend
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.github.dnvriend.oo.behavioral
18 |
19 | import com.github.dnvriend.TestSpec
20 |
21 | class IteratorPatternTest extends TestSpec {
22 | "" should "" in {
23 |
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/test/scala/com/github/dnvriend/oo/behavioral/ObserverPatternTest.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Dennis Vriend
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.github.dnvriend.oo.behavioral
18 |
19 | import com.github.dnvriend.TestSpec
20 |
21 | class ObserverPatternTest extends TestSpec {
22 | "" should "" in {
23 |
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/test/scala/com/github/dnvriend/oo/behavioral/StatePatternTest.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Dennis Vriend
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.github.dnvriend.oo.behavioral
18 |
19 | import com.github.dnvriend.TestSpec
20 |
21 | class StatePatternTest extends TestSpec {
22 | "" should "" in {
23 |
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/test/scala/com/github/dnvriend/oo/behavioral/TemplateMethodPatternTest.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Dennis Vriend
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.github.dnvriend.oo.behavioral
18 |
19 | import com.github.dnvriend.TestSpec
20 |
21 | class TemplateMethodPatternTest extends TestSpec {
22 | "" should "" in {
23 |
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/test/scala/com/github/dnvriend/oo/creational/FactoryPatternTest.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Dennis Vriend
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.github.dnvriend.oo.creational
18 |
19 | import com.github.dnvriend.TestSpec
20 |
21 | class FactoryPatternTest extends TestSpec {
22 | "" should "" in {
23 |
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/test/scala/com/github/dnvriend/oo/creational/SingletonPatternTest.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Dennis Vriend
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.github.dnvriend.oo.creational
18 |
19 | import com.github.dnvriend.TestSpec
20 |
21 | class SingletonPatternTest extends TestSpec {
22 | "" should "" in {
23 |
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/test/scala/com/github/dnvriend/oo/structural/AdapterPatternTest.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Dennis Vriend
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.github.dnvriend.oo.structural
18 |
19 | import com.github.dnvriend.TestSpec
20 |
21 | class AdapterPatternTest extends TestSpec {
22 |
23 | /**
24 | * ==TL;DR==
25 | * ''Convert the interface of a class into another interface clients expect.''
26 | *
27 | * ==Overview==
28 | * Convert the interface of a class into another interface clients expect. Adapter lets classes work together that
29 | * could not otherwise because of incompatible interfaces.
30 | *
31 | * ==Intent==
32 | *
33 | * ==Description==
34 | *
35 | * ==Componentization==
36 | *
37 | * ==Scala==
38 | */
39 | trait Adapter
40 | "" should "" in {
41 |
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/test/scala/com/github/dnvriend/oo/structural/CompositionPatternTest.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Dennis Vriend
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.github.dnvriend.oo.structural
18 |
19 | import com.github.dnvriend.TestSpec
20 |
21 | class CompositionPatternTest extends TestSpec {
22 | "" should "" in {
23 |
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/test/scala/com/github/dnvriend/oo/structural/DecoratorPatternTest.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Dennis Vriend
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.github.dnvriend.oo.structural
18 |
19 | import com.github.dnvriend.TestSpec
20 |
21 | class DecoratorPatternTest extends TestSpec {
22 | "" should "" in {
23 |
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/test/scala/com/github/dnvriend/oo/structural/FacadePatternTest.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Dennis Vriend
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.github.dnvriend.oo.structural
18 |
19 | import com.github.dnvriend.TestSpec
20 |
21 | class FacadePatternTest extends TestSpec {
22 |
23 | /**
24 | * ==TL;DR==
25 | * ''Provide a unified interface to a set of interfaces in a subsystem''
26 | *
27 | * ==Overview==
28 | * This pattern allows a (simplifying) object to unify a (potentially more complex) interface to a set of objects.
29 | * The Façade can often be viewed as an interface to a subsystem. It has the effect of simplifying the interface
30 | * between the clients and the subsystem objects. A client only has to deal with a single Facade object.
31 | * The Facade object then deals with the interactions with multiple subsystem objects.
32 | *
33 | * ==Intent==
34 | * Provide a unified interface to a set of interfaces in a subsystem`.
35 | * Facade defines a higher-level interface that makes the subsystem easier to use.
36 | *
37 | * ==Description==
38 | * Facade provides a simple interface to a complex subsystem. This is done in order to shield clients,
39 | * that does not need the lower level functionality provided by subsystems, from the complexity.
40 | *
41 | * Clients communicate with the subsystem by sending requests to a facade, the facade translates and handles
42 | * intercommunication between the subsystems
43 | *
44 | * Facades can be used to layer a system by decoupling subsystems. A specific facade functions as an entry point
45 | * to the subsystems it encapsulates.
46 | *
47 | * The use of facades as entry points promotes weak coupling between subsystem components and lets you vary the
48 | * components without affecting the clients.
49 | *
50 | * ==Componentization==
51 | * The things that differ are the `subsystems`, their intercommunication, which we cannot abstract over, and the
52 | * interface of the facade itself. Nothing stays the same between different instantiations, which means there is
53 | * nothing to modularize and reuse.
54 | *
55 | * ==Scala==
56 | * The trait Facade is an abstract facade with nested subsystem classes that are only accessible by Facade and subclasses.
57 | * The method foo is part of the public interface of the facade accessible by clients, it calls one of the subsystems with
58 | * another subsystem as argument. The singleton object FacadeA is an example of a concrete facade
59 | */
60 | trait Facade {
61 | // contains refs to `subsystems`
62 | type A <: SubSystemA
63 | type B <: SubSystemB
64 |
65 | val subA: A
66 | val subB: B
67 |
68 | def foo(num: Int): Int = subB.foo(subA, num)
69 | }
70 |
71 | class SubSystemA {
72 | def add(num: Int) = num + 1
73 | }
74 | class SubSystemB {
75 | def foo(sub: SubSystemA, num: Int): Int = sub.add(num)
76 | }
77 |
78 | object FacadeA extends Facade {
79 | override type A = SubSystemA
80 | override type B = SubSystemB
81 | override val subA = new SubSystemA()
82 | override val subB = new SubSystemB()
83 | }
84 |
85 | "Facade" should "provide a unified interface to a set of subsystems, and hide implementation details" in {
86 | FacadeA.foo(5) shouldBe 6
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/test/scala/com/github/dnvriend/oo/structural/ProxyPatternTest.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 Dennis Vriend
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.github.dnvriend.oo.structural
18 |
19 | import com.github.dnvriend.TestSpec
20 |
21 | class ProxyPatternTest extends TestSpec {
22 |
23 | /**
24 | * ==TL;DR==
25 | * ''It provides a surrogate or placeholder for another object to control access to it''
26 | *
27 | * ==Overview==
28 | * A proxy, in its most general form, is a class functioning as an interface to something else. The proxy could
29 | * interface to anything: a network connection, a large object in memory, a file, or some other resource that is
30 | * ''expensive or impossible to duplicate''. In short, a proxy is a wrapper or agent object that is being called by
31 | * the client to access the real serving object behind the scenes.
32 | *
33 | * GOF defines several types of proxies:
34 | *
35 | *