Am I designing and constructing my value objects correctly? - domain-driven-design

Sorry in advance if this question is unclear. Please tell me what to change to make it a better question.
I am currently maintaining a C# WinForm system where I'm trying to learn and use DDD and CQRS principles. Vaughn Vernon's Implementing Domain Driven Design is my main DDD reference literature.
The system currently uses legacy code which makes use of Data Aware Controls.
In the Asset Inventory Context, i have designed my aggregate root Asset which composes of multiple valueObjects which are standard entries in the system:
In this Context, i'm trying to implement a use case where the user can manually register an Asset to the system.
My current implementation is the following:
From Presentation Layer:
Upon loading the RegisterAssetForm.cs it loads the existing standard entry lists of Group, ItemName, etc. through the Data Aware controls, all consisting of data rows with columnsid: int and name: string.
When the user selects the desired ItemName, Group, PropertyLevel, Department, and Category, then clicks save, a command is performed:
RegisterAssetForm.cs
...
AssetInventoryApplicationService _assetInventoryServ;
...
void btnSave_Click(object sender, EventArgs e)
{
int itemNameId = srcItemName.Value // srcItemName is a custom control whose Value = datarow["id"]
int groupId = srcGroup.Value;
string categoryId = srcCategory.Value;
string departmentId = srcDepartment.Value;
string propLvlId = srcPropLevel.Value;
...
RegisterAssetCommand cmd = new RegisterAssetCommand(itemNameId, groupId, categoryId, departmentId, propLvlId);
_assetInventoryServ.RegisterAsset(cmd);
...
}
From Application Layer:
The AssetInventoryApplicationService depends on domain services.
AssetInventoryApplicationService.cs
...
IAssetRepository _assetRepo;
...
public void RegisterAsset(RegisterAssetCommand cmd)
{
...
AssetFactory factory = new AssetFactory();
AssetID newId = _assetRepo.NextId();
Asset asset = factory.CreateAsset(newId, cmd.ItemNameId, cmd.PropertyLevelId,
cmd.GroupId, cmd.CategoryId, cmd.DepartmentId);
_assetRepo.Save(asset);
...
}
From Domain Layer:
AssetFactory.cs //not my final implementation
...
public class AssetFactory
{
...
public Asset CreateAsset(AssetID id, int itemNameId, int propLvlId, int groupId, int categoryId, int departmentId)
{
ItemName itemName = new ItemName(itemNameId);
PropertyLevel propLvl = new PropertyLevel(propLvlNameId);
Group group = new Group(groupNameId);
Category category = new Category(categoryNameId);
Department department = new Department(departmentNameId);
return new Asset(id, itemName, propLvl, group, category, deparment);
}
...
}
Sample table of what fills my value objects
+------------+--------------+
| CategoryID | CategoryName |
+------------+--------------+
| 1 | Category1 |
| 2 | Category2 |
| 3 | Category3 |
| 4 | Category4 |
| 5 | Category5 |
+------------+--------------+
I know domain models must be persistence-ignorant that's why i intend to use surrogate identites (id field) in Layer Supertype with my valueobject to separate the persistence concern from the domain.
The main property to distinguish my value objects is their Name
From the presentation layer, i send the standard entry value as integer id corresponding to primary keys through a command to the application layer which uses domain services.
Problem
* Is it right for me to pass the standard entry's id when creating the command, or should I pass the string name?
* If id is passed, how do i construct the standard entry value object if name is needed?
* If name is passed, do i need to figure out the id from a repository?
* Or am I simply designing my standard entry value objects incorrectly?
Thanks for your help.

It looks to me that you may be confusing a Value Object and an Entity.
The essential difference is that an Entity needs an Id but a VO is a thing (rather than a specific thing). A telephone number in a CRM would likely be a VO. But it would likely be an Entity in if you are a telephone company.
I have an example of VO in this post which you may find helpful - you can get it here
To answer your 'Problems' more specifically:
If you are creating some entity then it can be advantageous to pass in the id to a command. That way you already know what the id will be.
You shouldn't be able to create an invalid value object.
Why can't you pass in the name and the ID? Again - not sure this is relevant to a Value Object
I think you have designed them incorrectly. But I can't be sure because I don't know your specific domain.
Hope this helps!

Related

Fetching all cucumber scenarios that have a particular tag

How can I fetch a list of all the scenarios that have a particular tag. For example
get all scenarios that have #checkout tag.
Lets assume you have 15-20 Scenarios/Scenarios Outline tagged with #checkout.
#checkout
Scenario Outline: Validation of UseCase Guest User Order Placement flow from Search
Given User is on Brand Home Page <Site>
And User searches for a styleId and makes product selection on the basis of given color and size
| Style_ID | Product_Size | Product_Color |
| TestData1 | TestData1 | TestData1 |
| TestData2 | TestData2 | TestData2 |
Then Clicking on Cart icon shall take user to Shopping Bag
Please follow this way to fetch name of scenarios.
File name Hook.java
#Before
public void setUpScenario(Scenario scenario){
String scenarioName = scenario.getName();
//Either you can write down name of the scenario under a file system like excel or implement in the way you want
}
Please lets know if you find it meaningful and it solved your problem.
Dry run to the rescue.
Dry run gives you a way to quickly scan your features without actually running them.
Try the following CucumberOptions annotations (this is Java/Junit version, but the idea applies everywhere)
#RunWith(Cucumber.class)
#CucumberOptions(plugin = { "pretty", "html:target/cucumber-html-report", "json:target/cucumber.json" }, glue = {
"some.stepdef" }, features = { "src/cucumberTest/featureFiles" }, tags = { "#now" }
,dryRun = true, strict=true)
public class CucumberNowTestDryRunner {
}
The cucumber report will look like this

How can i with Axon re-initialize some value with the same first InitAvailableQuantityCommand?

assume we have an stock. this stock should persist product id and available quantity. the user of this stock can frequently update(InitAvailableQuantityCommand) available quantity.
if some product has been sold, our system will get a soldEvent(DecreaseAvailableQuantityCommand) and available quantity for sold product should be decress.
it works well with aggregate below, until one thing,
if i try again to re-initialize stock with InitAvailableQuantityCommand, the event will be ignored and an error is thrown
An event for aggregate [3333] at sequence [0] was already inserted"
What i try to achive is following:
InitAvailableQuantityCommand (productId =1, quantity = 10)
DecreaseAvailableQuantityCommand (productId =1, quantity = 1)
DecreaseAvailableQuantityCommand (productId =1, quantity = 1)
now hier we have 8 available products more.
and it this moment user will re-initialize stock with 20 available products for productId 1. the user will send a new InitAvailableQuantityCommand (productId =1, quantity = 20) and it this moment it fail and doesn't work.
What do i wrong?
thx.
#NoArgsConstructor
#Aggregate
#Data
public class AvailableQuantityAggregate {
private String partnerId;
private String productId;
#AggregateIdentifier
private String productVariationId;
private int quantity;
#CommandHandler
public AvailableQuantityAggregate(InitAvailableQuantityCommand cmd) {
final ApplyMore apply = AggregateLifecycle.apply(AvailableQuantityInitializedEvent.builder()
.partnerId(cmd.getPartnerId())
.productId(cmd.getProductId())
.productVariationId(cmd.getProductVariationId())
.quantity(cmd.getQuantity())
.build());
}
#CommandHandler
public void handle(DecreaseAvailableQuantityCommand cmd) {
AggregateLifecycle.apply(AvailableQuantityDecreasedEvent.builder()
.productVariationId(cmd.getProductVariationId())
.quantity(cmd.getQuantity())
.build());
}
#EventSourcingHandler
protected void on(AvailableQuantityInitializedEvent event) {
this.productVariationId = event.getProductVariationId();
this.partnerId = event.getPartnerId();
this.productId = event.getProductId();
this.quantity = event.getQuantity();
}
#EventSourcingHandler
protected void on(AvailableQuantityDecreasedEvent event) {
this.quantity = this.quantity-event.getQuantity();
}
}
The InitAvailableQuantityCommand instantiates an Aggregate. Aggregates inherently have identity. As such, the Aggregate Identifier is in place to denote whom/what it is. When you are event sourcing, which you are by default in Axon, the Event Store will ensure that you will not add events with the same aggregate id and sequence number. When you are publishing the InitAvailableQuantityCommand a second time however, you are telling the framework to publish an event with the same aggregate id and sequence number.
Hence, your modelling solution should be a little different. The action (aka, the command) of instantiating the aggregate is different from resetting it. Thus I'd suggest to add a different command to reset your aggregate to it's initial values.
Judging from your code snippet, the InitAvailableQuantityCommand is handled by a constructor. This means that Axon expects to need to create a new instance of an aggregate. But as you are expecting to load an instance, there is a collision of identifiers (fortunately).
What you'd need to do, is create a different command that contains the same information, but is handled by an instance method. This might be what you want to do anyway, because there a conceptual/functional different between first-time initialization, and "resetting".
In future versions of Axon, we will support "create-or-update" kind functionality, where a single Command could fulfill both roles.

How can I get the Scenario Outline Examples' table?

In AfterScenario method, I want to get the rows from table "Examples" in Scenario Outline, to get the values in it, and search that specific values in the database
I know that this can be achieved by using Context.Scenario.Current...
Context.Scenario.Current[key]=value;
...but for some reason I'd like to be able to get it in a simpler way
like this:
ScenarioContext.Current.Examples();
----------- SCENARIO --------------------------------
Scenario Outline: Create a Matter
Given I create matter "< matterName >"
Examples:
| matterName |
| TAXABLE |
----------AFTER SCENARIO -----------------------------------
[AfterScenario()]
public void After()
{
string table = ScenarioContext.Current.Examples();
}
So if you look at the code for ScenarioContext you can see it inherits from SpecflowContext which is itself a Dictionary<string, object>. This means that you can simply use Values to get the collection of values, but I have no idea if they are Examples or not.
The best solution I came up with was to infer the examples by keeping my own static singleton object, then counting how many times the same scenario ran.
MyContext.Current.Counts[ScenarioContext.Current.ScenarioInfo.Title]++;
Of course, this doesn't work very well if you don't run all the tests at the same time or run them in random order. Having a table with the examples themselves would be more ideal, but if you combine my technique along with using ScenarioStepContext you could extract the parameters of the Examples table out of the rendered step definition text itself.
Feature
Scenario Outline: The system shall do something!
Given some input <input>
When something happens
Then something should have happened
Examples:
| input |
| 1 |
| 2 |
| 3 |
SpecFlow Hook
[BeforeStep]
public void BeforeStep()
{
var text = ScenarioStepContext.Current.StepInfo.Text;
var stepType = ScenarioStepContext.Current.StepInfo.StepDefinitionType;
if (text.StartsWith("some input ") && stepType == StepDefinitionType.Given)
{
var input = text.Split(' ').Last();
}
}

How to point to objects that aren't yet instantiated

I am preloading data on an app's first launch into Core Data, need to point to objects yet to be instantiated and can't figure out how to do this. I saw a similar question, though the solution isn't applicable in this situation.
Say I have 3 classes
class Person {
var nationOfBirth: Nation
...
}
class City {
var mayor: Person
...
}
class Nation {
var capitalCity: City
...
}
If i am loading an initial data set of nations, then cities, then people (or any other order) then no matter which order I load them in I will need to set instances yet to be instantiated (though I know they will be) and I'm struggling to figure out how to do this and will appreciate any help
One of this fields must be optional, because in your example you have cycle references. Also Optional field in this case must have week reference for another field to clear memory correctly in the end. Your code:
class Person {
var nationOfBirth: Nation
init(nation: Nation) {
nationOfBirth = nation
}
}
class City {
var mayor: Person
init(person: Person) {
mayor = person
}
}
class Nation {
weak var capitalCity: City?
}
//initialization
let nation = Nation()
let person = Person(nation: nation)
let city = City(person: person)
nation.capitalCity = city
In swift if you are declaring field in class without default initialisation you must initialise it in constructor(init). In your case you have 3 classes, each with one field of another class without default initialisation. So you need to initialise then in init method.
To initialise Person you need object of Nation, to initialise Nation you need object of City, to initialise City you need object of Nation, and again you need object of Person, than City, than Nation. As you you see it is infinity loop.
To solve this problem you need to break this loop. You can do it only with setting field of One class as optional (with ? in the end of type). After that you don't need to initialise that field in initialiser, because now it can contain nil(nothing).
If you don't need to initialise it in initialiser, you can now create member of class with optional field without object of another class and just set it in the end. In my code you can see, that City field in Nation is set as optional, so i can create member of Nation without initial City value(let nation = Nation()).
After that, as i have member of class Nation, i can create Person with initialiser that takes Nation object(let person = Person(nation: nation)).
In the same way as now we have created member of person we can create member of city(let city = City(person: person)).
In the end we have member of city, so we can set it to nation object, that was created at the beginning without city(nation.capitalCity = city).
About why we need weak reference in this case you can read hear - https://developer.apple.com/library/ios/documentation/swift/conceptual/swift_programming_language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097-CH20-XID_92

best practices with code or lookup tables

[UPDATE] Chosen approach is below, as a response to this question
Hi,
I' ve been looking around in this subject but I can't really find what I'm looking for...
With Code tables I mean: stuff like 'maritial status', gender, specific legal or social states... More specifically, these types have only set properties and the items are not about to change soon (but could). Properties being an Id, a name and a description.
I'm wondering how to handle these best in the following technologies:
in the database (multiple tables, one table with different code-keys...?)
creating the classes (probably something like inheriting ICode with ICode.Name and ICode.Description)
creating the view/presenter for this: there should be a screen containing all of them, so a list of the types (gender, maritial status ...), and then a list of values for that type with a name & description for each item in the value-list.
These are things that appear in every single project, so there must be some best practice on how to handle these...
For the record, I'm not really fond of using enums for these situations... Any arguments on using them here are welcome too.
[FOLLOW UP]
Ok, I've gotten a nice answer by CodeToGlory and Ahsteele. Let's refine this question.
Say we're not talking about gender or maritial status, wich values will definately not change, but about "stuff" that have a Name and a Description, but nothing more. For example: Social statuses, Legal statuses.
UI:
I want only one screen for this. Listbox with possibe NameAndDescription Types (I'll just call them that), listbox with possible values for the selected NameAndDescription Type, and then a Name and Description field for the selected NameAndDescription Type Item.
How could this be handled in View & Presenters? I find the difficulty here that the NameAndDescription Types would then need to be extracted from the Class Name?
DB:
What are pro/cons for multiple vs single lookup tables?
Using database driven code tables can very useful. You can do things like define the life of the data (using begin and end dates), add data to the table in real time so you don't have to deploy code, and you can allow users (with the right privileges of course) add data through admin screens.
I would recommend always using an autonumber primary key rather than the code or description. This allows for you to use multiple codes (of the same name but different descriptions) over different periods of time. Plus most DBAs (in my experience) rather use the autonumber over text based primary keys.
I would use a single table per coded list. You can put multiple codes all into one table that don't relate (using a matrix of sorts) but that gets messy and I have only found a couple situations where it was even useful.
Couple of things here:
Use Enumerations that are explicitly clear and will not change. For example, MaritalStatus, Gender etc.
Use lookup tables for items that are not fixed as above and may change, increase/decrease over time.
It is very typical to have lookup tables in the database. Define a key/value object in your business tier that can work with your view/presentation.
I have decided to go with this approach:
CodeKeyManager mgr = new CodeKeyManager();
CodeKey maritalStatuses = mgr.ReadByCodeName(Code.MaritalStatus);
Where:
CodeKeyManager can retrieve CodeKeys from DB (CodeKey=MaritalStatus)
Code is a class filled with constants, returning strings so Code.MaritalStatus = "maritalStatus". These constants map to to the CodeKey table > CodeKeyName
In the database, I have 2 tables:
CodeKey with Id, CodeKeyName
CodeValue with CodeKeyId, ValueName, ValueDescription
DB:
alt text http://lh3.ggpht.com/_cNmigBr3EkA/SeZnmHcgHZI/AAAAAAAAAFU/2OTzmtMNqFw/codetables_1.JPG
Class Code:
public class Code
{
public const string Gender = "gender";
public const string MaritalStatus = "maritalStatus";
}
Class CodeKey:
public class CodeKey
{
public Guid Id { get; set; }
public string CodeName { get; set; }
public IList<CodeValue> CodeValues { get; set; }
}
Class CodeValue:
public class CodeValue
{
public Guid Id { get; set; }
public CodeKey Code { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
I find by far the easiest and most efficent way:
All code-data can be displayed in a identical manner (in the same view/presenter)
I don't need to create tables and classes for every code table that's to come
But I can still get them out of the database easily and use them easily with the CodeKey constants...
NHibernate can handle this easily too
The only thing I'm still considering is throwing out the GUID Id's and using string (nchar) codes for usability in the business logic.
Thanks for the answers! If there are any remarks on this approach, please do!
I lean towards using a table representation for this type of data. Ultimately if you have a need to capture the data you'll have a need to store it. For reporting purposes it is better to have a place you can draw that data from via a key. For normalization purposes I find single purpose lookup tables to be easier than a multi-purpose lookup tables.
That said enumerations work pretty well for things that will not change like gender etc.
Why does everyone want to complicate code tables? Yes there are lots of them, but they are simple, so keep them that way. Just treat them like ever other object. Thy are part of the domain, so model them as part of the domain, nothing special. If you don't when they inevitibly need more attributes or functionality, you will have to undo all your code that currently uses it and rework it.
One table per of course (for referential integrity and so that they are available for reporting).
For the classes, again one per of course because if I write a method to recieve a "Gender" object, I don't want to be able to accidentally pass it a "MarritalStatus"! Let the compile help you weed out runtime error, that's why its there. Each class can simply inherit or contain a CodeTable class or whatever but that's simply an implementation helper.
For the UI, if it does in fact use the inherited CodeTable, I suppose you could use that to help you out and just maintain it in one UI.
As a rule, don't mess up the database model, don't mess up the business model, but it you wnt to screw around a bit in the UI model, that's not so bad.
I'd like to consider simplifying this approach even more. Instead of 3 tables defining codes (Code, CodeKey and CodeValue) how about just one table which contains both the code types and the code values? After all the code types are just another list of codes.
Perhaps a table definition like this:
CREATE TABLE [dbo].[Code](
[CodeType] [int] NOT NULL,
[Code] [int] NOT NULL,
[CodeDescription] [nvarchar](40) NOT NULL,
[CodeAbreviation] [nvarchar](10) NULL,
[DateEffective] [datetime] NULL,
[DateExpired] [datetime] NULL,
CONSTRAINT [PK_Code] PRIMARY KEY CLUSTERED
(
[CodeType] ASC,
[Code] ASC
)
GO
There could be a root record with CodeType=0, Code=0 which represents the type for CodeType. All of the CodeType records will have a CodeType=0 and a Code>=1. Here is some sample data that might help clarify things:
SELECT CodeType, Code, Description FROM Code
Results:
CodeType Code Description
-------- ---- -----------
0 0 Type
0 1 Gender
0 2 Hair Color
1 1 Male
1 2 Female
2 1 Blonde
2 2 Brunette
2 3 Redhead
A check constraint could be added to the Code table to ensure that a valid CodeType is entered into the table:
ALTER TABLE [dbo].[Code] WITH CHECK ADD CONSTRAINT [CK_Code_CodeType]
CHECK (([dbo].[IsValidCodeType]([CodeType])=(1)))
GO
The function IsValidCodeType could be defined like this:
CREATE FUNCTION [dbo].[IsValidCodeType]
(
#Code INT
)
RETURNS BIT
AS
BEGIN
DECLARE #Result BIT
IF EXISTS(SELECT * FROM dbo.Code WHERE CodeType = 0 AND Code = #Code)
SET #Result = 1
ELSE
SET #Result = 0
RETURN #Result
END
GO
One issue that has been raised is how to ensure that a table with a code column has a proper value for that code type. This too could be enforced by a check constraint using a function.
Here is a Person table which has a gender column. It could be a best practice to name all code columns with the description of the code type (Gender in this example) followed by the word Code:
CREATE TABLE [dbo].[Person](
[PersonID] [int] IDENTITY(1,1) NOT NULL,
[LastName] [nvarchar](40) NULL,
[FirstName] [nvarchar](40) NULL,
[GenderCode] [int] NULL,
CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED ([PersonID] ASC)
GO
ALTER TABLE [dbo].[Person] WITH CHECK ADD CONSTRAINT [CK_Person_GenderCode]
CHECK (([dbo].[IsValidCode]('Gender',[Gendercode])=(1)))
GO
IsValidCode could be defined this way:
CREATE FUNCTION [dbo].[IsValidCode]
(
#CodeTypeDescription NVARCHAR(40),
#Code INT
)
RETURNS BIT
AS
BEGIN
DECLARE #CodeType INT
DECLARE #Result BIT
SELECT #CodeType = Code
FROM dbo.Code
WHERE CodeType = 0 AND CodeDescription = #CodeTypeDescription
IF (#CodeType IS NULL)
BEGIN
SET #Result = 0
END
ELSE
BEGiN
IF EXISTS(SELECT * FROM dbo.Code WHERE CodeType = #CodeType AND Code = #Code)
SET #Result = 1
ELSE
SET #Result = 0
END
RETURN #Result
END
GO
Another function could be created to provide the code description when querying a table that has a code column. Here is an
example of querying the Person table:
SELECT PersonID,
LastName,
FirstName,
GetCodeDescription('Gender',GenderCode) AS Gender
FROM Person
This was all conceived from the perspective of preventing the proliferation of lookup tables in the database and providing one lookup table. I have no idea whether this design would perform well in practice.

Resources