• No results found

A place for everything, everything in its place Benjamin Franklin

N/A
N/A
Protected

Academic year: 2021

Share "A place for everything, everything in its place Benjamin Franklin"

Copied!
106
0
0

Loading.... (view fulltext now)

Full text

(1)

A place for everything,

everything in its place

(2)

I create software – holistic approach

● Technology (Java, Java EE) and Craftsmanship ● Design, architecture, usability

● Exploration of methodologies and best practices

I work as a trainer and consultant

● Java technologies

● Software engineering ● Community

● Leader of Lublin Java Users Group ● Blogger, speaker, publisher...

(3)

Challenges of software

Domain Driven Design

● introduction

● advanced topics

Technical and architectural

aspects of implementation

When to use DDD

Beyond DDD

(4)

Business software

No sophisticated stuff

● nothing like Fast Fourier Transform

Just simple operations...

● just multiplied by 1000:)

● synergy of simple components ● continuously changing

● We need a structure for dozens of

(5)

●You read code and understand nothing

● You can't see any rules or process

●You don't know how to translate

business requirements to code

●You change code and nothing works

●Now it's Your problem:)

(6)

Complexity

Essential

● inherent and unavoidable ● depends on problem

Accidental

● caused by chosen approach ● depends on solution

(7)

The Second Law of Thermodynamics

Entropy does not diminish

(8)

Cowards solution

Cowards solution;)

(9)

What would You change...

if You start everything from the beginning?

XML

Annotations

New server

New version

of the server

SOA

Dynamic language

Another web

framework;)

(10)

Insanity:

doing the

same

thing

over and over

again

(11)

Where is the problem?

Data access layer

Logic layer

(12)

It's all about the model

Model needs care

Model is a heart of the system

● reason why creating it ● main value

● advantage factor

Modelling is the toughest part

● weak model leads to failure

(13)

Unstructured design

Just adding new features – with no care about

model

● big ball of mud

● chaos and anarchy ● costs in long term

(14)

What model IS NOT

Database is

not

a model

just data structure – very technical

no behavior

static – we can't see whats going on

(15)

What model IS FOR

continous knowledge gathering

about rules

about dynamics

common

(client … developer) understanding of

domain

vocabulary

jargon

(16)

What model IS

Real model

description and simplification for current needs

no unimportant stuff – avoid mental overload

knowledge base - rules and behavior

(17)

●General concept

● technology and platform independent

●Set of design and analysis techniques

● focus on domain logic layer ● complexity reduction

● extension-ability and changeability

Pragmatic approach to OOD and OOA

(18)
(19)
(20)

„There is technically nothing new

or revolutionary in DDD,

there is only a guide to a better way of thinking.”

(21)

●Focus on behavioral model

●Common (Ubiquitous) Language ●Strategic modeling

● Core Domain ● Contexts

●Domain Layer – OOD ● Data and rules

● Roles that implicate responsibility ● Responsibility Driven Design

● GRASP ● SOLID

(22)

Language of the model

If domain expert don't understand

model

(23)

Problems with models

No model

just add features (somewhere;)

Model at the beginning, but no maintenance

● useless, inadequate documents

Distinct jargon leads to need of translation

● translation leads to errors and misunderstandings

Pure analytical model – fails fast

● unimplementable models are useless

(24)

Solution: Ubiquitous language

Model must be bind to code

● modeling in right paradigm – there is no pure

modeling support for procedural paradigm

● OOD techniques used by annalists ● building blocks...

Modeler must code

● coding is not low-skilled job

● result: creating implementable models

(25)

“Good picture is worth more than 1000 words”

●Not only UML

●Use any form that supports common understanding

and communication

● Client specific diagrams ● Sketch

(26)

System metaphor

Software design tend to be abstract

● hard to grasp

Organize design around metaphor

● absorb vocabulary

Find metaphor in real world that

describes your system

● loose, easy do understand ● large scale structure

(27)

Domain Model

Analysis Domain ModelDesign

+ ==

Domain Logic Layer

(28)

How to bind model and code?

Responsibility Driven Design

● Define roles that objects can play ● Roles determines responsibility

(29)

Layers

User interface

Infrastructure Application logic

Domain logic

Thin layer - just coordinates and delegates to domain

Heart of the system – model of the business concepts and rules

Technical capabilities - may exist as a few layers (persistence, messages, etc)

Presentation – can be very sophisticated; do not underestimate

(30)

Building Blocks of Domain Layer

Entities (not anemic)

Value Objects

Aggregates

Services (business)

Policies and Specifications

Business events

Factories

(31)

Entities

Object that need to be distinguished

● even if attributes are the same ● some ID

Not only data

Also behavior (business responsibility)

● characteristic ● essential

(32)

Value Objects

Just description of some characteristic

No distinction – no identity

VOs are the same if their attributes are the same

Typical usage:

● attributes of call between objects

Usually immutable - because has no identity

● therefore can be reusable – we don't care which instance

is being used

Usually no need to persist

(33)

Power of VOs

Expression of business concepts

adds

conceptual power

more meaningful than just String

May contain useful methods (instead of utils)

validation

constructor may validate input

Examples

● color, point (source, destination) ● address*, phone number

(34)

Candidates for VO

Strings with format limitations

● zip code

● name

Numbers with limitations

● percentage ● quantity

Business object's arguments/returns

● money – composed: amount + currency

– maybe can be exchanged?

● address

(35)

Services

Business Services

● Sometimes it just isn't a thing

● OO is not always proper approach

● OO is not always possible (human factor)

When can not find natural "home" in Entity/VO

Operation without state

● Defined in terms of other Building Block

Should not strip Entity/VO of all their

responsibilities

(36)

Aggregate

Cluster of objects (Entity/VOs)

● inner objects can reference each other inside ● boundary with one root

Outer entity is Aggregate root

● controls access - encapsulation

(37)

Encapsulation is virtue

human.getDigestionSystem().

getPeritoneum().getStomach(). add(new Sausage(2));

human.getDigestionSystem().

getPeritoneum().getStomach(). add(new Sausage(2));

human.eat(new Sausage(2));

public void eat(Food f){ if (! iLike(f))

thow new IDontLikeItException(f); this.digestionSystem.swallow(f);

}

human.eat(new Sausage(2));

public void eat(Food f){ if (! iLike(f))

thow new IDontLikeItException(f); this.digestionSystem.swallow(f);

(38)

@Entity

public class Order{

@Id private OrderId id;

@OneToMany private List<OrderItem> items = new ArrayList<OrderItem>();

private BigDecimal sum = new BigDecimal(0);

//.... status, createDate, rebatePolicy, productRepository,...

public void add(ProductId id, int quantity){

Product p = productRepository.load(id);

OrderItem oi = orderItemFactory.build(p, quantity, rebatePolicy); items.add(oi);

sum = sum.add(oi.getCost()); }

public void submit(){

if (status != Status.NEW)

throw new InvalidStateException();

status = Status.IN_PROGRESS; createDate = new Date();

eventsManager.handle(orderEventsFactory.orderSubmitted(this)); }

public Iterator<OrderItem> getOrderItems(){

return items.iterator();

} }

@Entity

public class Order{

@Id private OrderId id;

@OneToMany private List<OrderItem> items = new ArrayList<OrderItem>();

private BigDecimal sum = new BigDecimal(0);

//.... status, createDate, rebatePolicy, productRepository,...

public void add(ProductId id, int quantity){ Product p = productRepository.load(id);

OrderItem oi = orderItemFactory.build(p, quantity, rebatePolicy); items.add(oi);

sum = sum.add(oi.getCost()); }

public void submit(){

if (status != Status.NEW)

throw new InvalidStateException(); status = Status.IN_PROGRESS;

createDate = new Date();

eventsManager.handle(orderEventsFactory.orderSubmitted(this)); }

public Iterator<OrderItem> getOrderItems(){

return items.iterator(); }

(39)

Builder Design Pattern

(40)

●Use factory when creation of Entity/Aggregate is complicated ●Factory prevents from invalid Domain Object

● if “raw material” is invalid than factory vetoes ●Options

● add factory method to closely related objects ● if creating VO consider Singleton

●Architectural aspects

● when creating ORM Entities (out of IoC containter control) ● than inject dependencies manually in factory method

(41)

Repository

●Storage abstraction of objects (Entity/Aggregate) of some type

●Encapsulates DB access

● decoupling domain and technical stuff

●Retrieves objects by

● identity

● business criteria (in business Use Cases)

(42)

AOP Transactions

Application Service

OrdersRepository InvoicesRepository

OrmOrdersRepositoryImpl OrmInvoicesRepositoryImpl

Persistence Unit + Transactions Manager

(43)

Policy

Process as a Domain Object

● makes it explicit

● extends Ubiquitous Language

Simply: Strategy Design Pattern

Useful when there is more than one way to

carry out a process

● if process variations can be covered

by common interface

(44)

public class Order{

//FIXME: change to BigDecimal private double totalCost;

private TaxPolicy taxPolicy;

private RebatePolicy rebatePolicy; public void submit(){

totalCost-=rebatePolicy.calculateRebate(this); totalCost-=taxPolicy.calculateTax(this); ... } } <<interface>> TaxPolicy calculateTax(order) PolishTaxPolicy UKTaxPolicy

Policy example

(45)

IoC Container

Policy injection

getOrderFactory return OrderFactory OrderFactory PolishTaxPolicy setTaxPolicy

(46)

@Component

public class OrderFactory{

private TaxPolicy taxPolicy;

private RebatePolicy rebatePolicy; @Autowired

public OrderFactory(TaxPolicy tp, RebatePolicy rp){ this.taxPolicy = tp; this.rebatePolicy=rp;

}

public Order createOrder(...){ Order o = new Order(...);

o.setTaxPolicy(taxPolicy);

o.setRebatePolicy(rebatePolicy); }

(47)

@Component(„taxPolicy”)

public class PolishTaxPolicy implements TaxPolicy{ ...

}

<bean id="taxPolicy" class="x.y.PolishTaxPolicy">

@Configuration

public class PolicyFactories{

@Bean

public TaxPolicy taxPolicy() { return ... ;

} }

(48)

Policy – common pattern

Change classic thinking

● noun – class ● verb - method

Activity is an object

● method is just a signal to execute it

Unleash OO techniques

● polymorphic execution ● re-usability

(49)

Extension and Testability

● Extension without modification ● Strategy implies high cohesion

● Single policy can be tested

● Aggregate can be tested using policy stub/mock

Aggregate <<interface>> Strategy Concrete Business Impl Stub/Mock Test Impl Test Test

(50)

Events

Business Event is a signal from Aggregate

Aggregate is highly decoupled

● does not know about receiver type

(51)

@Entity

public class Order{

public void submit(){

if (status != Status.NEW)

throw new InvalidStateException();

status = Status.IN_PROGRESS; createDate = new Date();

eventsManager.handle(orderEventsFactory.orderSubmitted(this)); }

}

@Entity

public class Order{

public void submit(){

if (status != Status.NEW)

throw new InvalidStateException(); status = Status.IN_PROGRESS;

createDate = new Date();

eventsManager.handle(orderEventsFactory.orderSubmitted(this));

} }

(52)

What are Events for?

Decouple additional behavior

● adding new behavior without domain modification ● strong form of Inversion of Control

Collect state change (if we need to keep track

of entity changes history) – Events Sourcing

● events can signalize change

Asynchronous invocation

● When fast response is needed ● Distributed DDD...

(53)

Specification

Model of rules

Makes rules explicit

Can be used for Entity/Aggregate validation or

selection

public interface InvoiceSpecyfication{

public Collection<InvoiceProblem> check(Invoice i) }

public interface InvoiceSpecyfication{

public Collection<InvoiceProblem> check(Invoice i) }

(54)

public class CombinedInvoiceSpecyfication

implements InvoiceSpecyfication{

private List<InvoiceCriterion> criteria;

public Iterable<InvoiceProblem> check(Invoice i){ Collection<InvoiceProblem> result = new ...;

for (InvoiceCriterion criterion : criteria){ String problem = criterion.validate(i);

if (problem != null){

result.add(new InvoiceProblem(problem));

if (criterion.isCritical())

break;

return result; }}}}

public class CombinedInvoiceSpecyfication

implements InvoiceSpecyfication{

private List<InvoiceCriterion> criteria;

public Iterable<InvoiceProblem> check(Invoice i){ Collection<InvoiceProblem> result = new ...;

for (InvoiceCriterion criterion : criteria){ String problem = criterion.validate(i);

if (problem != null){

result.add(new InvoiceProblem(problem));

if (criterion.isCritical())

break;

return result; }}}}

public interface InvoiceCriterion{

public String validate(Invoice i);

public boolean isCritical(); }

public interface InvoiceCriterion{

public String validate(Invoice i);

public boolean isCritical(); }

(55)

Domain Layer (Business Logic) Aggregate Entity (Aggregate root) Entity Value Object business methods Delegate Load Save Business Service <<interface>> Policy

(Strategy Design Pattern)

Application Layer (Application Services, Use Case Agents)

PolicyImpl1 PolicyImpl2

Building Blocks - cooperation

<<interface>> Repository Factory Event Generate Create Delegate Delegate

(56)

Comparison to procedural approach

PROCEDURE orderService(o:TOrder); BEGIN ... END; TOrder = RECORD id: integer; ... END;

(57)
(58)

Strategic design

Distillation of Domains

Defining Bounded Contexts

(59)

You can't do everything perfect

Not enough knowledge

Not enough skilled people

Not enough time

Not enough money

Not enough time

Not enough money

Not enough time

Not enough money

Not enough time

Welcome to the real world, Neo

(60)

Focus on core domain

Core Domain

● Reason why we create system

● Main business features (give advantage to the client)

● Focus intellectual effort – invest time and best people

Supporting Domain

● Additional features – not critical

● Lower quality is acceptable

● Can be rewritten (someday - sure;)

Generic Domain

● Very specific (invoicing, math calculations)

(61)

Core Domain Strategies

Write Domain Vision Statement

● what brings value?

Keep it small

Invest the best people

(62)

Context

When distinct models are combined, we are in

troubles

● difficult to understand ● unreliable

(63)

Grand Unified Theory

Common anti-pattern

● one, big, corporate model ● meaningless

● one word in different contexts mean different thing

– responsibility – behavior

(64)

Bounded Context

When system grow up – complexity is too high

● can't look at the level of individual objects

Define context where model applies

Context is encapsulated

● communicates with outer word via interface ● inner business model is hermetic

● therefore it can evolve -changes don't spread

(65)

Contexts Strategies

Common Core Context can be defined

● Shared Kernel

Decouple distinct Domain Contexts

● Core (business)

(66)
(67)

Anti-corruption Strategies

Our brand new shiny nice system

Ugly legacy system Anti-corruption Layer Facade Adapter Service

(68)
(69)

Main rule

Platform, framework or technical architecture

should not influence arena of domain model

(70)

Useful techniques already

discussed

ORM - aggregates

Inversion of Control

● Dependency Injection - policies ● Events

● Aspect Oriented Programming – transactions (also

security) over application layer that impact Repositories

Design Patterns

(71)

Command-query Separation Paradigm

Method should play one of the following roles

command – executes some logic

query – return data

Multiple query should not affect the answer

Eliminates side effect

(72)

Class level violation

System level violation

Add an Order and return list of all orders

it's GUI functionality

but server API should offer 2 methods

private int x;

public int incrementAndReturn(){ x++;

return x; }

private int x;

public int incrementAndReturn(){ x++;

return x; }

(73)

(G)UI Business Logic Application Logic Command Facade ORM + JDBC Query DTO Repository/DAO

Command-query Responsibility Segregation

(74)

CqRS Characteristic

Processing C and Q is often asymmetrical

● Should be scaled separately

(75)

(G)UI Business Logic Application Logic Command Data provider/Finder Query DTO Repository/DAO DB 1 DB 2 Event (asynch) Events Bus + Event handlers Change

(76)

public class SearchDocumentsQuery implements Serializable{

private Status status;

private Date epiryDate;

private String[] titleWords;

private String[] contentWords; //Getters and setters/constructor }

public class SearchDocumentsQuery implements Serializable{

private Status status;

private Date epiryDate;

private String[] titleWords;

private String[] contentWords; //Getters and setters/constructor }

public class DocumentQueries /*implements SomeInterface*/{

public List<Document> search(SearchDocumentsQuery query){ //ORM return entities – simple case

}

public List<DocumentDTO> search(SearchDocumentsQuery query){ //SQL return UseCase relevant Data Transfer Object

} }

public class DocumentQueries /*implements SomeInterface*/{

public List<Document> search(SearchDocumentsQuery query){ //ORM return entities – simple case

}

public List<DocumentDTO> search(SearchDocumentsQuery query){ //SQL return UseCase relevant Data Transfer Object

} }

(77)

public class SearchDocumentsQuery implements Serializable{

private Status status;

private Date epiryDate;

private String[] titleWords;

private String[] contentWords; //ONLY getters

public SearchDocumentsQuery expired(){ status = Status.ACTIVE;

expiryDate = new Date();

return this; }

public SearchDocumentsQuery contains(String phrase){ String[] words = phrase.split(" ");

titleWords = words; contentWords = words;

return this; }

}

public class SearchDocumentsQuery implements Serializable{

private Status status;

private Date epiryDate;

private String[] titleWords;

private String[] contentWords; //ONLY getters

public SearchDocumentsQuery expired(){ status = Status.ACTIVE;

expiryDate = new Date();

return this; }

public SearchDocumentsQuery contains(String phrase){ String[] words = phrase.split(" ");

titleWords = words; contentWords = words; return this; } }

Query a'la DSL

(78)

public class OrderProductCommand implelents Serializable{ private int productId;

private int quantity;

//getters and constructor }

public class OrderProductCommand implelents Serializable{ private int productId;

private int quantity;

//getters and constructor }

public class Basket /*implements SomeInterface*/{ private Order order;

public void add(AddProductCommand cmd){

Product prod = productRepository.get(cmd.getProductId()); order.add(prod, cmd.getQuantity());

}

public void submit(SubmitOrderCommand cmd){

order.submit(cmd.getPayment(), cmd.getAddressInfo()); orderRepository.save(order);

eventsManager.orderSubmitted(new OrderSubmittedEvent(order)); }

}

public class Basket /*implements SomeInterface*/{ private Order order;

public void add(AddProductCommand cmd){

Product prod = productRepository.get(cmd.getProductId()); order.add(prod, cmd.getQuantity());

}

public void submit(SubmitOrderCommand cmd){

order.submit(cmd.getPayment(), cmd.getAddressInfo()); orderRepository.save(order);

eventsManager.orderSubmitted(new OrderSubmittedEvent(order)); }

}

(79)

public class OrderProductCommand extends Command{...}

public class OrderProductCommand extends Command{...}

public interface Handler<T> {

void handleMessage(T message) throws Exception; }

public interface Handler<T> {

void handleMessage(T message) throws Exception; }

(80)

public class AddProductHandler

implements Handler<AddProductCommand>{ private ProductRepository repository;

public void handleMessage(AddProductCommand message) { //...

} }

public class AddProductHandler

implements Handler<AddProductCommand>{ private ProductRepository repository;

public void handleMessage(AddProductCommand message) { //...

} }

public class CommandBus{

public void handle(Command cmd)

Collection<Handler<?>> matchedHandlers = handlers.get(message.getClass());

for (Handler handler : matchedHandlers){

//prepare environment (transactions, security, //inject current user, etc)

handler.handleMessage(cmd); }

//may generate message }

}

public class CommandBus{

public void handle(Command cmd)

Collection<Handler<?>> matchedHandlers = handlers.get(message.getClass());

for (Handler handler : matchedHandlers){

//prepare environment (transactions, security, //inject current user, etc)

handler.handleMessage(cmd); }

//may generate message

} }

(81)

Event Sourcing

If state of Aggregate at any given time is

needed to be rebuild

● not the same as Logs

"Inner" events

● represents current state of Aggregate ● events are stored in persistence layer

● Aggregate can be recreated to given state (point in

(82)

Temporal Object Pattern

Alternative to Event Sourcing

●whole state of Aggregate version persisted

●newest version is always available – no computation

(83)

Is DDD right for me?

Aspects of personality

Aspects of business domain itself

Aspects of project nature

(84)
(85)

Sometimes it's all about just collecting data

(with nice GUI)

(86)

DDD Prerequisites

Domain is not trivial

Team has experience and interest in OOP/OOD

You have access to domain experts

(87)
(88)

Advanced data models

Model Archetype – analytical “design pattern”

● standard

● "model component" that can be taken off the shelf,

customized, and instantiated in your own models

● adaptable – can be trimmed to fit actual

requirements

● extensible – can be extended to fit new

requirements

Catalog of models:

● Company structure and relationships, customers,

products, inventory, orders, scientific stuff (laboratory),...

(89)

How to model People and

Organizations?

Person Employee User Client

Inheritance is not a good idea to model roles:P Company

(90)

Party

(91)

General Idea

(92)

Example

(93)

Model

(94)

Details of Party

(95)

Person is a Party

(96)

Organization is a Party

(97)

Customer is a Party

(98)

Customer is a different story...

(99)

Behavior Driven Development

Agile software development technique

Encourages collaboration between

● developers, QA

● non-technical or business participants

BDD focuses on exposing internal logic

(typically business rules) to review by

stakeholders.

Native language in combination with the

ubiquitous language of DDD

(100)

Data Context Interaction

New programming paradigm

● needs dynamic language syntax (mixins, traits)

Trygve Reenskaug

● co-inventor of Object Oriented ● inventor of MVC

Mainstream OO languages

● are not Object Oriented

(101)

Use Case flow and global algorithm Classes Classes Classes Classes Classes

(102)

Data

● core

● basically dumb ● may contain basic

responsibility Interactions ● business responsibility ● operates on data Context

● Whole Use Case ● or just few steps ● adds meaning to

the data

Full working Objects

● makes sense only in context ● methods implies by current role

(103)

DDD summary

No rocket science

“Just” rational usage of OOA and OOD

Pragmatic approach to complexity of business

logic

Most important things:

● Ubiquitous Language ● Strategic Design

Building Block are

not

the most important

thing:P

(104)

Code should mean something

(105)

Sławomir Sobótka

Dziękuję za uwagę

więcej...

http://art-of-software.blogspot.com slawomir.sobotka@bottega.com.pl

(106)

Photo credits

● http://www.norcalblogs.com/commission/images/house-of-cards.jpg ● http://nirmukta.com/wp-content/uploads/2009/08/complexity.jpg ● http://www.basicbonsai.com/wp-content/uploads/2009/11/brazilian_rain_tree.jpg ● http://i659.photobucket.com/albums/uu312/mlee4elbow/prof_chaos02.jpg ● http://a.images.blip.tv/Unclephilms-puppetTest1168.jpg ● http://www.individual-i.org/images/logo-3sizes.jpg ● https://star-cosmos.com/starcomsos_blog/wp-content/uploads/2009/08/human-body.jpg ● http://media.photobucket.com/image/train%20wreck/wgman21/train_wreck.jpg ● http://englishrussia.com/images/mig_factory/1.jpg ● http://upload.wikimedia.org/wikipedia/commons/thumb/b/b7/2000_core-repository02_hg.jpg/600px-2000_core-repository02_hg.jpg ● http://www.alacera.com/images/model_city_3d.jpg ● http://www.faqs.org/photo-dict/photofiles/list/5558/7276chess_pawn.jpg ● http://www.shoemoney.com/images/nuke.jpg ● http://www.dzieci.legnica.pl/grafikacms/niejadek250.jpg ● http://fineartamerica.com/images-medium/conwy-castle-and-the-telford-suspension-bridge-north-wales-mal-bray.jpg ● http://fandomania.com/wp-content/uploads/2008/05/terminator.jpg ● http://www.directortom.com/storage/square%20peg.jpg?__SQUARESPACE_CACHEVERSION=1223602138853 ● http://dontsqueezethejj.com/blog/wp-content/uploads/2008/07/macgyver.jpg ● http://www.wilsonsalmanac.com/images2/shakespeare9.jpg ● http://arnoldit.com/wordpress/wp-content/uploads/2008/10/mismatch.jpg ● http://images1.wikia.nocookie.net/matrix/images/thumb/3/32/Neo.jpg/300px-Neo.jpg ● http://i69.photobucket.com/albums/i71/nynja24me/guns/M-67handgrenade.jpg ● http://www.travelooce.com/pics/sunset_sailing.jpg

References

Related documents

As explained in Section 1.3, any equivalent martingale measure can be identified with a pricing rule: It extends the given prices of the primary assets to a larger space of

In this context, the notion co-benefits in Annex 56 refers to all benefits (positive or negative) resulting from renovation measures related to energy and carbon emissions

It's boring. You spend most of the game staring at your plants as they ripen. Then you make the wine and return to staring at your plants. There're a few other bits like buying plots

We launched our management division in 1999 and have since operated and maximized profitability for an impressive portfolio of hotels and residential properties on behalf of

measured 0.018–0.39 ppm of naturally occurring diacetyl in short-term (8–11 min) area samples collected at breath- ing zone height next to a commercial grinder that processed 11 kg

For purposes of determining the amount of any monthly premium, if an individual enrolls in both a qualified health plan and a plan described in section 1311(d)(2)(B)(ii)(I) of

1) Affordable housing can be more expensive to produce than market-rate housing due to the more complex financing packages and the influences of location, which raise

In this study, the first to be conducted among first-year medical students in any private university in Nigeria, the aim is to identify stressors and factors associated with