1 / 18

Architectures 2

Architectures 2. Architecture Patterns Design Patterns. Layer Supertype. Some functionality is frequently common for all classes In a module or layer Separated out in a ”layer supertype”. Domain layer. Data mapper ”layer”. Testing and Speed Considerations. Not all tests need real DB

Download Presentation

Architectures 2

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Architectures 2 Architecture Patterns Design Patterns

  2. Layer Supertype • Some functionality is frequently common for all classes • In a module or layer • Separated out in a ”layer supertype” Domain layer Data mapper ”layer”

  3. Testing and Speed Considerations • Not all tests need real DB • Some test domain • Some test mapper • Some test DB access • When focus is not db • A fake db will do • Replace data mapper with one using in-memory data • Mappers need same interface • Apply DIP Request Data Mapper Presentation Logic Use Create/Read Object-oriented Domain Model Access Data Source Logic

  4. What We Have • We have two setups with mapper classes • Each with its own layer supertype

  5. What we Need • The mappers should be interchangeable, so we need something like this • The DB client should not bother whether it gets a Linq, SQL or Dummy • The RoomMapper interface needs to be the same • The client depends on an interface, not on a particular mapper • DIP with dynamic replacement of the actual mapper possible

  6. Arrange Mappers According to Domain Classes • What the client is concerned about • To get a room mapper, a person mapper, a booking mapper • Not interested in whether it is linq, sql or dummy • Need an orthogonal structure • One mapper from each technology need to implement RoomMapper, PersonMapper etc • ISP: Treat classes according to their roles (interfaces)

  7. Where the Mapper Comes From • The client can get its mapper in two different ways • Have it given to itself from the outside: Dependency Injection • Ask someone for it • We may let it ask for it • Depending on setups, we may want to have different setups • LinqBookingMapper, LinqRoomMapper, LinqPersonMapper • DummyBookingMapper, DummyRoomMapper, DummyPersonMapper • But not • LinqBookingMapper, DummyRoomMapper, SqlPersonMapper • The setup needs to be consistent

  8. Solution: Abstract Factory • Use design pattern Abstract Factory • One factory delivers a consistent set of mappers

  9. Applying Patterns • Refactoring • Architecture Patterns • Design Patterns • Singleton • Abstract Factory

  10. Where The Factory Comes From: Singleton • With different factories, one is the current one • Assign that one to a singleton • Similar to a global variable • MapperFactory.Instance returns the current factory • Every time you need a new room mapper • roomMapper = MapperFactory.Instance.MakeRoomMapper(); • The factory singleton manages a current instance in terms of MapperFactory • That is an abstract class • We need to inject an instance of a concrete class into the singleton • MapperFactory.SetFactory(new LinqMapperFactory());

  11. The Singleton namespace DataMappers { abstract public class MapperFactory { private static MapperFactory instance; public static void SetFactory(MapperFactory factory) { instance = factory; } public static MapperFactory Instance { get { return instance; } } abstract public RoomMapper MakeRoomMapper(); abstract public PersonMapper MakePersonMapper(); abstract public BookingMapper MakeBookingMapper(); } }

  12. Subclasses Implement the Factory Methods using DataMappers; namespace LinqDataMappers { public class LinqMapperFactory : MapperFactory { public override RoomMapper MakeRoomMapper() { return new LinqRoomMapper(); } public override PersonMapper MakePersonMapper() { return new LinqPersonMapper(); } public override BookingMapper MakeBookingMapper() { return new LinqBookingMapper(); } } }

  13. The Factory Hierarchy • The Instance is typed MapperFactory • So it may return any of the subclasses • It needs to be instantiated • See demo • Principle: LSP • The clients will not notice any difference

  14. The Complete Mapper Solution

  15. Using the Mappers • Now we know how to create and manage mappers in a consistent way • Through an Abstract Factory • The application still needs to get hold of a mapper to read and save data • The abstract superclass Mapper may act as a mapper holder • A Singleton-like property for each mapper • Mapper.BookingMapper.GetAll() • A method to clear the current mapper of each kind • Called at the end of a user transaction • Needed in order to reset the Identity Map • Which is needed to avoid duplicate in-memory objects • Mapper.ClearBookingMapper() • A method to clear all the current mappers • Mapper.ClearMappers()

  16. Implementing the Mapper Access Mechanisms • A singleton-like static accessor property in abstract class Mapper • private static BookingMapper bookingMapper; • public static BookingMapper BookingMapper{get{if (bookingMapper == null)bookingMapper = MapperFactory.Instance.MakeBookingMapper();return bookingMapper;}} • Resetting a mapper • public static void ClearBookingMapper() {bookingMapper = null;} • Resetting all the mappers • public static void ClearMappers(){ClearRoomMapper();ClearPersonMapper();ClearBookingMapper();}

  17. Consequences of Mapper and Identity Map • Clients may use the BookingMapper etc properties directly • Mapper.BookingMapper always gives a (new or old) booking mapper • Call ClearMappers() when done with a user transaction • That is after the last update of the user transaction • Or when starting a new one with fresh data • When you know that you are done with your domain objects • Resets the identity map in the mapper • Assures that reading the same record several times does not result in several copies of the corresponding domain object in memory • Triggers fresh reading from the database on the next read operation • In case some other user has made any changes

  18. Complete Example: Menu Selection ”Display All” • Reloading all the bookings • privatevoid allToolStripMenuItem_Click(object sender, EventArgs e){LoadData();} • privatevoid LoadData(){Mapper.ClearBookingMapper();Display(Mapper.BookingMapper.GetAll());} • privatevoid Display(IList<Booking> list){bookingBindingSource.DataSource = from item in listorderby item.Venue.Name ascending, item.FromTime ascendingselect item;}

More Related