Title: design of distributed applications
1design of distributed applications
- ???? ???, ???? ?? ?????,???? ????????
2Keep is Small
- In OO fine grained objects are good design.
- It allows control, easy behavior substitution and
clarity. - As a consequence, theres a great deal of
interaction between objects mainly methods
invocation.
3Practical Problems
- Its all good in a single address space
application (one machine, one process). - What happens when application is among other
processes? - What happens when application is among other
machines?
4Its pay time
- Methods invocation becomes expensive
- Often marshalling is required.
- Security comes into the picture.
- Packets switching time become significant.
5Solution
- Minimize the number of methods calls.
- Do it by getting a coarse grained interface.
- Lets make a pattern of it!
- Well call it. Remote Façade.
6Remote Facade
- Its basically giving a small interface (coarse
grained) to a collection of remote, fine grained
objects. - It has no domain logic.
- All it does is to translate the coarse grained
method onto the underlying fine grained objects.
7Example - accessors
8Some considerations to be done
- Obviously now we transfer information in bulks.
- Serialize it! The serialization magic.
- But its not always possible to serialize a part
of domain logic because of its complexity. - For that well use Data Transfer Object up
ahead.
9How coarse ?
- Some prefer a façade per use-case
- Some prefer per object.
- Some prefer to count them on one hand fingers.
- It all depends in application.
10Other responsibilities for a facade
- Security (Check ACLs)
- Apply transactional protocol
- But dont ever put there domain logic.
11When to use it
- Whenever theres a need for a remote access for
fine grained objects. - Between presentation and domain model, when they
run on different processes. - Dont use it over same address space.
12Detailed example Web Service
- At its heart a Web service is nothing more than
an interface for remote usage. - Web Service holds the basic advice
- Build your functionality in a fine-grained
manner and then layer a Remote Facade over the
fine-grained model As such, Web Service is a
- Remote Facade
13(No Transcript)
14Some details
- Artist, Album Track are the fine grained,
domain model objects. - We use DTO, explained later, to pass the
information.
15The Remote Façade class Service definition.
- class AlbumService...
- WebMethod
- public AlbumDTO GetAlbum(String key)
- Album result new AlbumFinder()key
- if (result null)
- throw new SoapException ("unable to find album
with key " key, SoapException.ClientFaultCode)
- else return new AlbumAssembler().WriteDTO(result
) -
16And the Service itself
- The public service itself is exposed thought the
WSDL. - Important thing in this example
- The Layering Approach
- Design an application without distribution, then
layer the distribution ability on top of it with
- Remote Facades and Data Transfer
- Objects (Explained ahead).
17Data Transfer Object
- Definition
- How it Works?
- Serializing the Data Transfer Object
- Assembling a Data Transfer Object
- When to use it?
- Example
18Definition Goal
- When working with a remote interface such as
Remote Façade - each call is expensive.
- The simplest solution is DTO
- An object that carries data between processes in
order to reduce the number of method calls - In Sun community Value Object
19Constrains
- Serializable
- Needs to be understood by both sides of the wire
20How It Works?
- The DTO is a bunch of fields and the getters and
the setters for them - The DTO usually carries much more data than what
the remote object request. - It aggregates data from all the server objects
that the remote object is likely to want data
from. - The DTO will be simplified form of the
data(primitives and simple string,date ect)
21How It Works?
- Keeping the structure between the DTOs a simple
graph structure - The design of the DTO would be corresponding to
the needs of a particular client - Example for DTO Record Set
- Is the DTO for a SQL database
22Serializing the Data Transfer Object
- Usually the DTO is responsible for serializing
itself into some format that will go over the
wire. - Depends on
- What can run over the connection itself
- Whats on either side of the connection
- How easy the serialization
23Serializing the Data Transfer Object
- A number of platforms provide built in
serialization for simple objects. For example - Java has built in binary serialization
- .NET has built in binary and XML serialization
24Serializing the Data Transfer Object
- The mechanism
- Provide accessors and read and write
serialization - The mechanism needs to be made in a way that both
ends of the connection will work with.
25Serializing the Data Transfer Object
- One of the most common issues you face is whether
to use a text or binary serialization form. - Text serialization are easy to read and to learn
whats being communicated - The big disadvantages with text are
- Needs more bandwidth
- Performance penalty
26Serializing the Data Transfer Object
- Synchronization problem
- Whenever the server changes
- the definition of the DTO, the client updates
as well but in practice this may not happen.
27Serializing the Data Transfer Object
- the serialization mechanism can make the problems
more or less painful. - With a pure binary serialization of a DTO the
result will be that its communication is entirely
lost, since any change to its structure usually
causes an error on deserialization(Even adding aa
optional field)
28Serializing the Data Transfer Object
- Other serialization schemes can avoid this like
- XML serialization - can usually be written in a
way that makes the classes more tolerant of
changes.
29Assembling a Data Transfer Object from Domain
Objects
- Usually an assembler is used on the server side
to transfer data between the DTO and any domain
objects. - As a general rule, the domain model should be
kept independent of the external interfaces. - A DTO doesnt know about how to connect with
domain objects for that reason we should keep the
DTO and the domain objects independent.
30Assembling a Data Transfer Object from Domain
Objects
- As a result we will make a separate assembler
object responsible for creating a DTO from the
domain model and updating the model from it
31(No Transcript)
32(No Transcript)
33When to Use It?
- Use a Data Transfer Object whenever you need to
transfer multiple items of data between two
processes in a single method call. - In particular, when you want to communicate
between components using XML. - its much better to use a DTO that encapsulates
the XML DOM, - especially since the Data Transfer Object is so
easy to generate
34When to Use It?
- To act as a common source of data for various
components in different layers. Each component - makes some changes to the Data Transfer Object
and then passes it on to the next layer(Example
.NET)
35When to Use It?
- There are some alternatives to Data Transfer
Object - simply to use a setting method
- with many arguments or a getting method with
several pass-by reference arguments. - The problem many languages allow only one object
as a return value - It can be used for updates, but it cant be used
for retrieving information -
36When to Use It?
- Use a form of string representation directly,
without an object acting as the interface to it. - The problem is that everything
- else is coupled to the string representation
- Its good to hide the precise representation
behind an explicit interface (changing the
string or replace it with a binary structure is
easy)
37Example Transferring Information About Albums
(Java)
Domain Model
A class diagram of artists and albums.
38Example cont.
- The data to transfer related to the linked
objects - This is the structure for the data transfer
object
39Example cont.
- class AlbumAssembler...
- public AlbumDTO writeDTO(Album subject)
- AlbumDTO result new AlbumDTO()
- result.setTitle(subject.getTitle())
- result.setArtist(subject.getArtist().getName())
- writeTracks(result, subject)
- return result
-
40Example cont.
- private void writeTracks(AlbumDTO result, Album
subject) - List newTracks new ArrayList()
- Iterator it subject.getTracks().iterator()
- while (it.hasNext())
- TrackDTO newDTO new TrackDTO()
- Track thisTrack (Track) it.next()
- newDTO.setTitle(thisTrack.getTitle())
- writePerformers(newDTO, thisTrack)
- newTracks.add(newDTO)
-
- result.setTracks((TrackDTO) newTracks.toArray(n
ew TrackDTO0)) -
41Example cont.
- private void writePerformers(TrackDTO dto, Track
subject) - List result new ArrayList()
- Iterator it subject.getPerformers().iterator()
- while (it.hasNext())
- Artist each (Artist) it.next()
- result.add(each.getName())
-
- dto.setPerformers((String) result.toArray(new
String0)) -
42Example cont.
- class AlbumAssembler...
- public void createAlbum(String id, AlbumDTO
source) - Artist artist Registry.findArtistNamed(source.ge
tArtist()) - if (artist null)
- throw new RuntimeException("No artist named "
source.getArtist()) - Album album new Album(source.getTitle(),
artist) - createTracks(source.getTracks(), album)
- Registry.addAlbum(id, album)
-
43Example cont.
- private void createTracks(TrackDTO tracks,
Album album) - for (int i 0 i lt tracks.length i)
- Track newTrack new Track(tracksi.getTitle())
- album.addTrack(newTrack)
- createPerformers(newTrack, tracksi.getPerformer
s()) -
-
44Example cont.
- private void createPerformers(Track newTrack,
- String performerArray)
- for (int i 0 i lt performerArray.length i)
- Artist performer
- Registry.findArtistNamed(performerArrayi)
- if (performer null)
- throw new RuntimeException("No artist named "
performerArrayi) - newTrack.addPerformer(performer)
-
-
45Example cont.
- Reading the DTO involves quite a few decisions
- Noticeable here is how to deal with the artist
names as they come in.Here the requirements are
that artists should already be in a Registry when
the album, is being created. A different create
method might decide to create artists when
theyre mentioned in the Data Transfer Object.
46Example cont.
- class AlbumAssembler...
- public void updateAlbum(String id, AlbumDTO
source) - Album current Registry.findAlbum(id)
- if (current null)
- throw new RuntimeException("Album does not
exist " source.getTitle()) - if (source.getTitle() ! current.getTitle())
current.setTitle(source.getTitle()) - if (source.getArtist() ! current.getArtist().get
Name()) - Artist artist Registry.findArtistNamed(source.
getArtist()) - if (artist null)
- throw new RuntimeException("No artist named "
source.getArtist()) - current.setArtist(artist)
-
- updateTracks(source, current)
-
47Example cont.
- private void updateTracks(AlbumDTO source, Album
current) - for (int i 0 i lt source.getTracks().length
i) - current.getTrack(i).setTitle(source.getTrackDTO(i
).getTitle()) - current.getTrack(i).clearPerformers()
- createPerformers(current.getTrack(i),
source.getTrackDTO(i).getPerformers()) -
-
48Example cont.
- As for updates you can decide to either update
the existing domain object or destroy it and
replace it with a new one. - The question here is whether you have other
objects referring to the object you want to
update.
49Example cont.
- Serialization procedure
- Get the data structure for the Data Transfer
Object - You need to decide how to serialize it. ( In
Java you get free binary serialization simply by
using a marker interface.) This works completely
automatically for a Data Transfer Object - 3. However, text-based serialization is often
necessary. For this example then, Well use XML.
50Example cont.
- Serializing Using binary (Java)
- When you use the binary serialization it means
that the Data Transfer Object classes on both
sides of the wire are kept in sync. In order to
make the transfer more tolerant we use a map for
the serialization.
51Example cont.
- class TrackDTO...
- public Map writeMap()
- Map result new HashMap()
- result.put("title", title)
- result.put("performers", performers)
- return result
-
- public static TrackDTO readMap(Map arg)
- TrackDTO result new TrackDTO()
- result.title (String) arg.get("title")
- result.performers (String)
arg.get("performers") - return result
-
52Example cont.
- Now, if I add a field to the server and use the
old client, although the new field wont be
picked up by the client, the rest of the data
will transfer correctly
53Example cont.
- In order to avoid much of the tedium in writing
the serialization and deserialization we can use
the - reflective routines.
54Example cont.
- class DataTransferObject...
- public Map writeMapReflect()
- Map result null
- try
- Field fields this.getClass().
- result new HashMap()
- for (int i 0 i lt fields.
- result.put(fieldsi.getName(),
-
- catch (Exception e)
- throw new ApplicationException (e)
-
- return result
-
55Example cont.
- public static TrackDTO readMapReflect(Map arg)
- TrackDTO result new TrackDTO()
- try
- Field fields result.getClass().getDeclaredFie
lds() - for (int i 0 i lt fields.length i)
- fieldsi.set(result, arg.get(fieldsi.getName
())) -
- catch (Exception e)
- throw new ApplicationException (e)
-
- return result
-
56Example cont.
- Serializing Using XML (Java)
- Well write read and write an XML
- element to represent each DTO class.
57Example cont.
- class AlbumDTO...
- Element toXmlElement()
- Element root new Element("album")
- root.setAttribute("title", title)
- root.setAttribute("artist", artist)
- for (int i 0 i lt tracks.length i)
- root.addContent(tracksi.toXmlElement())
- return root
-
58Example cont.
- static AlbumDTO readXml(Element source)
- AlbumDTO result new AlbumDTO()
- result.setTitle(source.getAttributeValue("title")
) - result.setArtist(source.getAttributeValue("artist
")) - List trackList new ArrayList()
- Iterator it source.getChildren("track").iterato
r() - while (it.hasNext())
- trackList.add(TrackDTO.readXml((Element)it.next(
))) - result.setTracks((TrackDTO)
trackList.toArray(new TrackDTO0)) - return result
-
59Example cont.
- class TrackDTO...
- Element toXmlElement()
- Element result new Element("track")
- result.setAttribute("title", title)
- for (int i 0 i lt performers.length i)
- Element performerElement new
Element("performer") - performerElement.setAttribute("name",
performersi) - result.addContent(performerElement)
-
- return result
-
60Example cont.
- static TrackDTO readXml(Element arg)
- TrackDTO result new TrackDTO()
- result.setTitle(arg.getAttributeValue("title"))
- Iterator it arg.getChildren("performer").iterat
or() - List buffer new ArrayList()
- while (it.hasNext())
- Element eachElement (Element) it.next()
- buffer.add(eachElement.getAttributeValue("name")
) -
- result.setPerformers((String)
buffer.toArray(new String0)) - return result
-
61Example cont.
- Of course, these methods only create the elements
in the XML DOM. - To perform the serialization we need to read and
write text. - Since the track is transferred only in the
context of the album, we just need to write this
album code.
62Example cont.
- class AlbumDTO...
- public void toXmlString(Writer output)
- Element root toXmlElement()
- Document doc new Document(root)
- XMLOutputter writer new XMLOutputter()
- try
- writer.output(doc, output)
-
- catch (IOException e)
- e.printStackTrace()
-
-
63Example cont.
- public static AlbumDTO readXmlString(Reader
input) - try
- SAXBuilder builder new SAXBuilder()
- Document doc builder.build(input)
- Element root doc.getRootElement()
- AlbumDTO result readXml(root)
- return result
-
- catch (Exception e)
- e.printStackTrace()
- throw new RuntimeException()
-
-
64The End