Date post: | 24-May-2015 |
Category: |
Software |
Upload: | david-dawson |
View: | 520 times |
Download: | 1 times |
Architectural Flexibility
using Groovy
What kind
of
Code is Best?
Object Oriented
or
Functional?
Strongly Typed
or
Weakly Typed?
To Meta
or
Not to Meta?
Data
or
Type
Why?
●Non functional requirements
[tx/ sec, latency, deployment etc]
●Non functional requirements
[tx/ sec, latency, deployment etc]
●Developer Comprehension
●Non functional requirements
[tx/ sec, latency, deployment etc]
●Developer Comprehension
●Coding Style
●Non functional requirements
[tx/ sec, latency, deployment etc]
●Developer Comprehension
●Coding Style
●Data Model(s)
●Non functional requirements
[tx/ sec, latency, deployment etc]
●Developer Comprehension
●Coding Style
●Data Model(s)
●Others … [bias...?]
Forces on Code
What kind
of
Code is Best?
WrongQuestion
Core Domain
Application PoliciesBusiness Rules
Core Domain
Application PoliciesBusiness Rules
Core Domain
Application PoliciesBusiness Rules
REST
Core Domain
Application PoliciesBusiness Rules
REST
Events
Core Domain
Application PoliciesBusiness Rules
RESTProvided API
Events
Core Domain
Application PoliciesBusiness Rules
RESTProvided API
UserDSL
Events
Context
Core Domain
Application PoliciesBusiness Rules
RESTProvided API
UserDSL
Events
Core Domain
Application PoliciesBusiness Rules
Core Domain
Application PoliciesBusiness Rules
Core Domain
Application PoliciesBusiness Rules
Core Domain
Core Domain
Application PoliciesBusiness Rules
Core Domain
Forces
Core Domain
Application PoliciesBusiness Rules
Core Domain
Forces● Express Type
Core Domain
Application PoliciesBusiness Rules
Core Domain
Forces● Express Type
● Understand Identity
Core Domain
Application PoliciesBusiness Rules
Core Domain
Forces● Express Type
● Understand Identity
● Use Ubiquitous Language
Core Domain
Application PoliciesBusiness Rules
Core Domain
Forces● Express Type
● Understand Identity
● Use Ubiquitous Language
● Relatively high code churn
OrderMenu
Recipe
OrderMenu
Recipe
orderId
recipeId
menuId
class OrderService {
}
def process( def order ) { if (valid(order)) { dispatch(order) persist(order) return OrderResult.SENT } OrderResult.INVALID //or similar}
class OrderService {
}
process( Order order ) { if (valid(order)) { dispatch(order) persist(order) return OrderResult.SENT } OrderResult.INVALID //or similar}
OrderResult
class OrderService {
}
process( Order order ) { if (valid(order)) { dispatch(order) persist(order) return OrderResult.SENT } OrderResult.INVALID //or similar}
OrderResultvalidateAndDispatch
Core Domain
Application PoliciesBusiness Rules
REST
Events
Provided API
UserDSL
Events
Events
EventsEvent Processor
EventsEvent Processor
Subscription
Subscription
Subscription
EventsEvent Processor
Subscription
Subscription
Subscription
Event
EventsEvent Processor
Subscription
Subscription
Subscription
Events
Forces
Event Processor
EventsEvent Processor
Forces● Performance
EventsEvent Processor
Forces● Performance
● Technically focused, technical language
EventsEvent Processor
Forces● Performance
● Technically focused, technical language
● No interest in type or identity
EventsEvent Processor
Forces● Performance
● Technically focused, technical language
● No interest in type or identity
● Interest in functionality
EventsEvent Processor
Forces● Performance
● Technically focused, technical language
● No interest in type or identity
● Interest in functionality
● Data/ algorithm oriented
class EventProcessor {
List<Subscription> subscriptions
}
void process(Message message) { subscriptions.findAll { it.canHandle(message) }.each { it.dispatch(message) }}
class EventProcessor {
List<Subscription> subscriptions
}
void process(Message message) { subscriptions.findAll { it.canHandle(message) }.each { it.dispatch(message) }}
class EventProcessor {
List<Subscription> subscriptions
}
void process(Message message) { subscriptions.findAll { it.canHandle(message) }.each { it.dispatch(message) }}
200k messages : 450ms
class EventProcessor {
List<Subscription> subscriptions
}
void process(Message message) { for(Subscription sub in subscriptions) { if(it.canHandle(message)) {
it.dispatch(message) } }}
80ms200k messages : 450ms
class EventProcessor {
List<Subscription> subscriptions
}
@CompileStaticvoid process(Message message) { for(Subscription sub in subscriptions) { if(it.canHandle(message)) {
it.dispatch(message) } }}
30ms200k messages : 450ms 80ms
Core Domain
Application PoliciesBusiness Rules
REST
Events
Provided API
UserDSL
Core Domain
Application PoliciesBusiness Rules
REST
Events
Provided API
UserDSL
Core Domain
Application PoliciesBusiness Rules
REST
Core Domain
Application PoliciesBusiness Rules
REST
Core Domain
Application PoliciesBusiness Rules
RESTDomain Transformer
Core Domain
Application PoliciesBusiness Rules
RESTDomain Transformer
Forces
Core Domain
Application PoliciesBusiness Rules
RESTDomain Transformer
Forces● Interested only in integration
Core Domain
Application PoliciesBusiness Rules
RESTDomain Transformer
Forces● Interested only in integration
● Designed to remove type
Core Domain
Application PoliciesBusiness Rules
RESTDomain Transformer
Forces● Interested only in integration
● Designed to remove type
● Affinity with Data & Values
Core Domain
Application PoliciesBusiness Rules
RESTDomain Transformer
Forces● Interested only in integration
● Designed to remove type
● Affinity with Data & Values
● Data Transformation
class OrderTransformer {
}
def send(Message message) { RestMessage msg = New RestMessage()
msg.txt = message.text target.doProcessing(msg)}
class OrderTransformer {
}
def send(Message message) { RestMessage msg = New RestMessage()
msg.txt = message.text target.doProcessing(msg)}
class OrderTransformer {
}
def send(Message message) { RestMessage msg = New RestMessage()
msg.txt = message.text target.doProcessing(msg)}
msg.txt = message.text target.doProcessing(msg)
def msg=[txt:message.text] target.doProcessing(msg)
def transformer = { target, message ->
def msg=[text:message.text] target.doProcessing(msg) }
def transformer = { message, target ->
def msg=[txt:message.text] target.doProcessing(msg) }
transformer = transformer.curry(aTarget)transformer(text:”Hello GGX!”)
Core Domain
Application PoliciesBusiness Rules
REST
Events
Provided API
UserDSL
UserDSL
UserDSL
Domain SpecificLanguage
UserDSL
Domain SpecificLanguage
Forces
UserDSL
Domain SpecificLanguage
Forces● User Comprehension
UserDSL
Domain SpecificLanguage
Forces● User Comprehension
● Expressiveness
UserDSL
Domain SpecificLanguage
Forces● User Comprehension
● Expressiveness
● Ease of Use versus Intuitive
def orders = Order.findAllByUserName(“someone”)
def orders = Order.findAllByUserNameAndOrderTax\BetweenOrOrderValueLessThanAndAddress1Like( “someone”, 5, 6, 15.20, “%Some Street%”)
def orders = Order.findAllByUserNameAndOrderTax\BetweenOrOrderValueLessThanAndAddress1Like( “someone”, 5, 6, 15.20, “%Some Street%”)
def orders = Order.findAll { username == “someone” orderValue in [5 .. 6] address1 =~ “%Some Street%”}
def orders = Order.findAllByUserNameAndOrderTax\BetweenOrOrderValueLessThanAndAddress1Like( “someone”, 5, 6, 15.20, “%Some Street%”)
def orders = Order.findAll { username == “someone” orderValue in [5 .. 6] address1 =~ “%Some Street%”}
Core Domain
Application PoliciesBusiness Rules
Core Domain
Forces● Express Type
● Understand Identity
● Use Ubiquitous Language
● Relatively high code churn
Core Domain
Application PoliciesBusiness Rules
Core Domain
Forces● Express Type
● Understand Identity
● Use Ubiquitous Language
● Relatively high code churn
List<Order> findAuthorisedRecords(User user) {
List<Order> orders = Orders.list()
List<Order> selectedOrders = new ArrayList<>();
for(Order order: orders) { if(order.user == user) { SelectedOrders << order }}
return Collections.sort(selectedOrders)
}
List<Order> findAuthorisedRecords(User user) {
List<Order> orders = Orders.list()
List<Order> selectedOrders = new ArrayList<>();
for(Order order: orders) { if(order.user == user) { SelectedOrders << order }}
return Collections.sort(selectedOrders)
}
List<Order> findAuthorisedRecords(User user) {
List<Order> orders = Orders.list()
List<Order> selectedOrders = new ArrayList<>();
for(Order order: orders) { if(order.user == user) { selectedOrders << order }}
return Collections.sort(selectedOrders)
}
List<Order> findAuthorisedRecords(User user) {
def orders = Orders.list()
def selectedOrders = []
for(def order: orders) { if(order.user == user) { selectedOrders << order }}
return Collections.sort(selectedOrders)
}
List<Order> findAuthorisedRecords(User user) {
def orders = Orders.list()
def selectedOrders = orders.findAll { order.user == user}
return Collections.sort(selectedOrders)
}
List<Order> findAuthorisedRecords(User user) {
def orders = Orders.list()
return orders.findAll { order.user == user}.sort { order.id}
}
List<OrderDetails> findAuthorisedRecords(User user) {
def orders = Orders.list()
return orders.findAll { it.user == user}.sort { it.id}.collect { it as OrderDetails}
}
Understand Context
Understand Context
Identify Forces
Understand Context
Identify Forces
Drive Code
Understand Context
Identify Forces
Drive Code
Reject Dogma
Questions
@davidthecoder
Thank you!
@davidthecoder