Showing posts with label design patterns. Show all posts
Showing posts with label design patterns. Show all posts

Jul 2, 2015

Single Repository, one Aggregate

A Repository as defined in Domain Driven Design manages a single Aggregate. An aggregate may contain many entities, and value objects, but will have a single object as its root. Many of the Dao and even now some of the Repository implementations I see do not follow this, they are more likely to have a Repository per entity, than a Repository per aggregate, and of course in some cases this is required for various reasons.

Ok, to start out we need our POM (or you can use Gradle), which configures our dependencies and plugins. We use a starter for Spring Data JPA, which pulls in Spring Data JPA and all of it's suggested dependencies such as Hibernate. We also need a database and a database driver so we configure H2. Since we are inheriting from the Spring Platform BOM we don't need to specify versions as it can configure them for us. We of course want to use Java 8 and specify our Application class so we will be able to run mvn spring-boot:run at the end.


Next Let's configure our application to show the SQL that it is running, this isn't required. You need to put application.properties in src/main/resources.

Now we need to create our Entities, let's start at the entity Bar that is the deepest part of the Aggregate root. It extends AbstractPersistable so that we get an Auto Incrementing or Sequenced id. We also use AbstractPeristable because for our task we require that our entities implement Persistable, as it changes the behavior of save on the repository if your objects are new.

Next let's create Foo, it is much the same, but you'll notice the @OneToOne that specifies CascadeType.ALL. This is important as without it persist and merge won't work.
Alright, let's put together our repository, we could just make a CrudRepository, but let's show off some paging too. You'll notice that you have to pass the Entity and it's Primary Key identifier type to the PagingAndSorting interface, the single method that we specify will find all the Foos by the nested baz property, using a LIKE '%mystring%' query. Spring data will parse this interface and make an implementation for you automatically.

You can create other lastly we do our Application, which is not designed to be a web server (it will exit immediately). The @SpringBootApplication makes Spring Boot able to start the app and scan for components appropriately. We also Enable JPA repositories using the @EnableJpaRepositories. It's main method (not recommended to prepopulate data this way), creates and save several Foos with nested bars, then I demonstrate a way that you can page the saved objects 2 at a time whilst filtering by that like statement, only 3 of the 4 entities saved will return.

The full source is available here.

Oct 23, 2013

Providing with Providers and Bread::Board

So when I started using Dependency Injection the following problem happened, how do I Inject this dependency when the container is not accessible at this point. Ok, that sentence even confused me a little bit, so what do I mean. Let's say I have a Repository for Products that is injected into my controller. Each Product stored has one or more ProductVariants that is part of it's aggregate, which itself has Nested Categories. Loading this entire graph at once would be relatively expensive, so we decide to do some lazy loading via DBI in the classes. One problem, how on earth do we Inject a Database Handle all the way down to Categories. Most of these ways are against DI, but they are solutions to the problem, there are also ways to combine these. Also, your model class having a database handle is probably bad design itself, but I'm not going to get into that. Sadly I've done every one of these

Manual

Well at least you aren't hard coding the way to read your config file, or your database driver. You're smart enough to rely on an Interface rather than an Implementation. This is fraught with so many problems. Firstly if your web server (assuming it's a web application) is getting any kind of traffic at all you'll end up creating tons of database connections, you'll also be reading that config file every time (ok I forget if Config::Merge caches to memory, it might, but often when I see people design this way, they are basically slurping the file every time). Someday 5 years from now, someone is going to hate you because now they need to support replicants... and the config needs to support more connection strings, which means modifying every place you've done this. Also, you've completely lost the ability to inject your dependencies for whatever reason you may want to.

Inheritance/Composition

Ok, this is a little bit better than before, at least now you have Inverted your dependencies, you could provide the config or the database handle to the class. You've also put the code in a centralized place so it's easy to change when you need to. You're still reading the file fairly often, though perhaps less because it now depends on how long Product variant is alive. So what happens if your connection is lost? We still have a connection for each class, a connection that may now be held much longer. Why does Product Variant need access to the config? this is a violation of the Law of Demeter.

Naive Service Locator

We need to get rid of knowledge of the config. We can do this by using a Service Locator, which is simply a well known service to retrieve other services, usually a global singleton. In our example we're at least smart enough to allow ourselves to change the class out via injection for testing. We no longer have tons of connections or config reads. However, we now have a new problems, what happens when our Application Server forks a process and we lose the database connection? What about when our locator gets more complex, like nested containers, that could change or access, specifically with replication. Also our class is now directly dependent on Bread::Board, and its interface. At least we've stopped caring how our database handle is built. Our locator is a global singleton, and we can't change our Container class for testing.

Robust Service Locator

Ok, so this is much better we can now configure which locator instance we use at runtime. We have removed the dependency on the Bread::board interface. There is no longer a problem with database connections being dropped. However, our container is still a global singleton, and our class still knows about it, which again, law of Demeter.

Dependency Injection and Pass it down

For now I've been basically ignoring other classes because with all of these other approaches they aren't really a concern because you would do the same thing in every class, fetch your service. Much of the code is required here anyways, we always would have to do the sql, the transforms the loops. Dependency inversion is the opposite, do not think of how to retrieve the dependency instead have the dependency provided. But this becomes tricky to think of when you're 3 or more levels deep in your hierarchy. One way to do it simply pass the reference. We create a specific problem here, our Repository lifecycle is a singleton so we need to ensure re-connection, thus we must inject the connector which means we are immediately dependent on the DBIx::Connector interface. This doesn't seem that tricky until you add more than one service, which still may not seem that bad, until you have to add one later, and oh my god, now you're modifying several classes.

Dependency Injection with Providers

This next and final sample show's one way of doing this with Providers. A little context on a Provider first, a Provider is simply an object that can be used to retrieve a an instance of an object you need. It's really just a kind of factory, but tends to be specific to dependency injection, in scenarios where you need a new instance of an object each time. It seems that it might also work well for other cases, such as objects with a longer lifespan than a new instance on every request from the injector, but shorter than a permanent singleton. In short a provider should be able to provide you with an instance on request, without requiring to to depend on retrieval.

The code that I'm demonstrating will not work currently practical scenario, meaning one where variant parameters are required. I've opened a bug about resolving the issue. In the mean time, the patch is simple and you could apply it yourself. You could use BUILDARGS to rename an alternate key to the primary hashkey, in your models. You could also just define each model service one at a time instead of looping them, and actually validating their parameters.

You may note that I've removed the config, this was simply so I could build the code out so it works in completion. It maybe advantageous not to put config processing code in the Dependency injector, but rather provide the config to Bread::Board::Declare at the constructor via required services. This way of doing things requires much more code, but is also much more flexible. Every piece of the model, even those hat could not normally be accessed by the injector, can now have it's dependencies injected to it.

Jun 4, 2012

New Module: MooseX::RemoteHelper (RFC)

Background

I have spent much of the last year writing and refining Remote Facades. At this point I've worked with SOAP, REST/JSON, and RPC url-form-encoded API's. One of the hardest parts I've found is dealing with the serialization of a Data Transfer Object with a Perl interface into whatever the remote is expecting. When I started I didn't know of these patterns, or really anything about these patterns. I highly recommend reading Patterns of Enterprise Application Architecture) if you want to know more about these patterns or things like Active Record and MVC.

problem

The problems I've encountered are many, including the fact most remotes are buggy or have a cludgy interface. Though there's nothing you can do about a remote api that you don't control, you can make your local API much cleaner and more native. Doing this however comes with a few challenges. One is that you have to map a local attribute name to a remote attribute name, because Perl uses underscores, and Java uses camel case, e.g postal_code and postalCode. The second problem is that many times the value of the attribute in its perl native form is not what the remote wants, e.g. perl boolean "1" remote "Y", or a DateTime object to W3C formatting. This second is not quite the same as mapping, because mapping is one to one, this translation could be turning an array into a comma separated string. The third problem, I didn't run into until after I "solved" the first , is how should I deal with nested complex objects (one's that can't be just converted to just a string).

My first naive remote facade was very procedural and simply assembled top to bottom, in part because it was based on SOAP::Lite, and in part because I had yet to figure out a better way. This resulted in a giant unwieldy if/then chain. Obviously my translations were just inline too.

The next thing I tried was using triggers to construct a request hash to pass to XML::Compile::SOAP. This worked better as the hash constructing code was kept right next to the attribute, so if I needed to modify the local or remote attribute, I could just go look at the attribute and the trigger tied to it.

After that I tried to use a map to translate from the native attribute name to the remote attribute name. This may have been more successful had it worked more like the Assembler in the Remote Facade. But ult imately since we were developing a rapidly changing API it seemed to bog me down, this is because I was changing the attributes on both sides of the mapping and thus the mapping at the same time (so at least 3 places). Here I was just manually dealing with the translation from a W3C DateTime format to the object I needed.

a solution

When I got assigned to yet another API and found myself doing yet another mapping and translation I decided that I needed to solve the problem. Enter the first iteration of MooseX::RemoteHelper. The first tie I used it with the form-url-encoded API so it was only needed for a single level of key, value pairs. .

Once I determined how to create MX::RemoteHelper it was simply a matter of using Class::MOP::Class API's to iterate all the attributes. The source of CompositeSerialization will give you some idea of how I did this.

Then I went back to apply this to a previous module, because the technique appears to be cleaner. Unfortunately I ran into a problem, this other API was a complex data structure, and how best to provide nested hashrefs and arrayrefs. Though I was now armed with Patterns I didn't know of one that would solve the problem. Fortunately a quick flip through the Gang of Four brought me to the Composite Pattern. I used this to write the recursive CompositeSerialization so that if I had a sufficiently complex nested structure I could simply create another object to deal with that. Here's a full example:

use 5.014;
use warnings;
use Data::Dumper;

package MessagePart {
    use Moose;
    use MooseX::RemoteHelper;
    with 'MooseX::RemoteHelper::CompositeSerialization';

    has array => (
        remote_name => 'SomeColonDelimitedArray',
        isa      => 'ArrayRef',
        is        => 'ro',
        serializer => sub {
            my ( $attr, $instance ) = @_;
            return join( ':', @{ $attr->get_value( $instance ) } );
        },
    );

    __PACKAGE__->meta->make_immutable;
}
    
package Message {
    use Moose;
    use MooseX::RemoteHelper;

    with 'MooseX::RemoteHelper::CompositeSerialization';

    has bool => (
        remote_name => 'Boolean',
        isa      => 'Bool',
        is        => 'ro',
        serializer => sub {
            my ( $attr, $instance ) = @_;
            return $attr->get_value( $instance ) ? 'Y' : 'N';
        },

    );

    has foo_bar => (
        remote_name => 'FooBar',
        isa      => 'Str',
        is        => 'ro',
    );

    has part => (
        isa      => 'MessagePart',
        remote_name => 'MyMessagePart',
        is        => 'ro',
    );

    __PACKAGE__->meta->make_immutable;
}

my $message
= Message->new({
    bool    => 0,
    foo_bar => 'Baz',
    part    => MessagePart->new({ array => [ qw( 1 2 3 4 ) ] }),
});

say Dumper $message->serialize

Which should give you this data structure:

Request For Comment

I've recently released a Trial version of MooseX::RemoteHelper to CPAN. I'm currently refactoring Business::CyberSource to use it, and it appears to be solid. What I'd like to know what people think of the module names, method names and any other comments they might have. I haven't been entirely sure that I've been naming things correctly while writing this, or that the code couldn't be better in other ways. If there's functionality you wish it had but doesn't let me know.