October 2013 - Posts

DDDSunflower

I’ve been doing some kata’s lately and have decided that there is quite a lot in a name. Working on another project that has things named more generically has been a somewhat difficult adjustment to get used to.

The funny thing is that I think that one of the big reasons people opt for descriptive names is because object taxonomy / classification is difficult! In order to properly classify things you have to know exactly how they relate to one another. This implies that you need to know everything there is to know about all of the classes to do it properly. Hopefully there is that someone on the team that is willing to help classify classes as they are created. Otherwise a large project can quickly become chaos!

Some time ago I stopped drawing “layers” or “tiers” in my architectural diagrams. The reason is that it’s too easy to get confused and think that DDD has anything in common with N-Tier architecture. There may be some similarities on the surface of things which makes them diagram like each other, but really they couldn't be more different. In DDD the Domain objects (those objects who contribute directly to solving the problem) should be the center of the universe. When it comes to DDD, I really take this concept to heart!

Because objects that those domain objects depend on may not actually be considered domain objects themselves, I opt to omit any/all of these infrastructure objects from my architecture diagram. Why?

  1. When drawn this way it’s easy to think that the database is the center of your architecture.
  2. Infrastructure objects, including database access objects, are not very helpful when looking at the high-level architecture because we mostly want to see how these domain objects interact with each other.
  3. They easily clutter and detract from the purpose of the diagram. After all, the purpose of an architectural diagram is not to show every class or even every kind of class. That is what a class diagram is useful for, and an architectural diagram is a little more abstract.
  4. By the very nature of DDD, our domain experts need to be able to consume this diagram. That’s tricky when a bunch of objects they don’t understand are also there.

Therefore, when I diagram architecture, I use circles with arrows indicating directionality of the dependency. If I draw an infrastructure object, I will make it rectangle to set it apart from my domain objects.

Inversion of Control

Again, I recommend omitting infrastructure dependencies (aka concerns or cross-cutting concerns) altogether! Another consideration is that sometimes these domains can have hierarchical dependencies. For example, I could have a namespace ‘MyCompany.OrderProcessing.Orders.SalesTax.Providers.SimpleTax’. Because of this hierarchical tendency our domains can literally have smaller domains inside of them. After all, Order Processing is a main domain of the MyCompany company. Orders are going to be at the center of the Order Processing activity. SalesTax deals specifically with orders but is outside the core functionality of an order. Providers are likely required to hook into other systems, and we want to have a specific implementation for SimpleTax.  This is the level to which we want to abstract.

It’s going to take skill and perhaps a helpful domain expert to decide where objects outside of this domain live. For example does a customer belong in the ‘MyCompany’ domain or do we assume we have no customers unless we have orders and put them in the ‘MyCompany.OrderProcessing’ domain.

Inevitably someone is going to be setting up the projects and get confused about what projects to make and what to name them. My advice is simply this:

  1. Create a project in domain spaces where there would/could be code reuse.
  2. Place interfaces and enumerations in the domain level right above where those interfaces would be implemented (MyCompany.OrderProcessing.Orders.SalesTax.Providers in the example.)
  3. Build to expand, but don’t put every class in it’s own project. I.E. Order and OrderItems probably belong in the same place (MyCompany.OrderProcessing.Orders). This is because while OrderItems are a closely related and do not make a lot of sense without one another.
  4. Name data and other infrastructure objects like you would name the domain objects, but remember they are not domain objects!
  5. Avoid “Common”, “Shared”, “Utility”, or any other project that is a dumping ground for miscellaneous. Classify these classes and put them where they belong, even if they are not domain objects.
  6. Test projects should test only one domain project. This will allow the tests to follow the project as it evolves.
  7. Avoid naming the projects with the term “Service” unless they are actually a service like a WCF service.
  8. Avoid naming projects with the suffix “Interfaces”. This is because the parent domain level should take care of providing the interface. Only in rare cases should the interfaces be included independently. This only creates mostly-empty projects that are unneeded. Additionally it’s more helpful to provide an abstract class for a inheriting class to implement rather than just an interface.
  9. Avoid separating an objects data from it’s behavior (e.g. You should not split SalesTax into SalesTaxData and SalesTaxManager).
  10. Use static sparingly! You loose your ability to use dependency injection when you use a static class. In non-static classes, only create a static method when all of the following are true:
    1. Both the class and the method are stateless.
    2. None of the inputs to a method are a complex type. You should especially other domain objects. Sealed classes are okay.
    3. There would never be a need to alter (or for any other reason inherit from) the class.
    4. The return type from this class is not a complex type or is a sealed type.

Another question that is often asked is how to deal with multiplicities. I.E. what class would deal with finding all orders for a given customer. The answer is that it depends. Many times it would be  appropriate to put a “GetOrdersByCustomer” call into Order, but many other times it should go into a peer class (a class in the same namespace) or a parent scope class. In this particular example I would probably create a class named `MyCompany.OrderProcessing.Orders.

For this particular example let’s consider how this domain would be organized and where these pieces would fit-in. Lets say that we have a class called `MyCompany.OrderProcessing.Orders.Order`. This class will deal with order information, both the creation of new orders and as an historical order. You would probably want an `MyCompany.OrderProcessing.Orders.OrderHistoryProvider` or `OrderProvider`, or something of the like. Just remember your SOLID principles!

A couple of weeks ago I listened to a presentation by Scott Hanselman about scaling your life. One of the many great pieces of advice is to blog about something rather than email an answer.

So this afternoon my good friend Alex asked me how we used to convert Vector PDF images to XAML Drawing Brushes so they can be applied to objects as a background, for instance. The vector part of that sentence is important because any rasterized portions of the PDF will be excluded in this process.

Well, there really isn’t a lot to it, so here are the instructions:

  1. Open up your vector image in Inkscape. Inkscape can open a wide variety of images, including PDF.
    image
  2. Click File –> Save As. Drop the Save as Type to “Microsoft XAML (*.xaml)” and save the file as XAML. Once the file is saved you can open it up in Internet Explorer to see how the conversion process went. The problem though, is that this is painting directly to a canvas and is not packaged to be used as a background.
    image
  3. Open up Microsoft Expression Blend. Create a new project. Open up the XAML for the main file and replace it with the contents from your file from step 2.
    image
  4. Select all parts of the drawing then select Tools –> Make Brush Resource –> Make Drawing Brush Resource. This will pop open a dialog that will give you some options about where to define this resource and what it should be named.
    image

So now your technically done. The contents of the Resource Dictionary now contain your new Drawing Brush Resource. To test it out clear all content from your main window except for the Window and Grid objects. Click the whitespace and open the properties inspector. Click the square dialog button for the Background and select Local Resource and the name you gave your brush. You should now be able to see your image:

image

The reason it is stretched is because your drawing brush will stretch to fill it’s contents. If you have a look at the XAML of the main window shows you will see the following XAML:

<Grid Background="{DynamicResource MindfireBackground}">
That’s pretty much it!
with no comments
Filed under: , , ,