I have a design where I want to be able to assign one or more command objects to an entity, which will then use these commands as part of its workflow. Something like assigning add-on features to a user's account, for argument's sake.
I understand the Command pattern and how this fits, but my question is one of persistence. If I have a list of commands, where each user account can have its own list of commands, and let's assume for argument's sake that the only thing important about the command is its system Type, and/or they all have the same properties. What's the best way to persist that when it comes time to implement my data layer?
I was considering doing it as a many to many relationship between the accounts table and the commands/features table, where the latter table follows a TPH strategy (i.e. all commands persisted in the same table). That seems to be the most clean way of doing it, but I wanted to see if anyone else follows a different strategy?
Do you instead make it a 1: many relationship, where any two accounts that have the same feature added have a different instance of that feature? Or is there a better way that I'm not thinking of at all?
Many-to-many with TPH looks ok to me.
Though I wonder your design decision to attach commands to different users, seems like you are trying to use them for authorization | permission purposes, instead of implementing normal authorization system using Role Based Security, or ACL. If it as the case then I would probably use role based security at internal level and for UI commands that are created dynamically based on internal security rather then statically stored in DB.
Related
How to Retrieve All Active Inventories from All tenants and companies to one custom screen selector in Acumatica??
In ISV Solution I am trying this. How to approach this scenario
Disclaimer: What you are asking appears to venture into a use case that is contrary to a foundational design element of Acumatica ERP - isolation of tenants within a single database. While I have a similar use case in mind in which I need to do the same, use of any of these suggestions should be weighed seriously against your business requirements and operating constraints.
After discussion with some Acumatica Developer MVP's and Acumatica staff, there is no SUPPORTED method for doing this directly with tables already containing a CompanyID field. However, here are a few possible ways to achieve your desired results.
Create alternate SQL Tables / Acumatica DAC's without CompanyID and CompanyMask so that the data can be shared. This will require keeping the supplemental table data in sync.
UNSUPPORTED (This will fail an ISV Certification) - Create a SQL view that excludes CompanyID and CompanyMask and an Acumatica DAC for that view. This will allow visibility to the data, regardless of tenant, without having to create or maintain duplicate data. Again, I was advised strongly against this approach in the same statement of it being possible.
Use an alternative tool to access the data in the SQL database if you have direct access to the database. This tool would have to access the database in a way completely independently of PXData so that all database queries do not automatically receive the "CompanyID = X" in the where clause.
It was mentioned that you might do something with impersonating other users, but I don't have any experience with that. I'm not sure if it would allow cross-tenant data access, but I don't believe it would allow viewing more than 1 tenant even if it does let you view another tenant at all.
My understanding is that the first option is the preferred method to stay within Acumatica in a supported way. The third option could be valid if you already use other analytics tools like Cognos.
Coming from a sql background. When I want to limit access to data based upon certain attributes of a user, I can create a view and use the view as a filter in limiting what data a user sees based upon the criteria in the view. This approach relies upon relationships and so far it has worked for me. Looking at NoSql and the shift in strategy and concept, I am confused about how to implement this consdering the nature of NoSql. What is the NoSql approach to a problem such as this? When users are only privy to certain rows based upon their user type? For example, say an administrator can see all of the records for a particular group and a generic user can only see their records and certain group level items, group photos, group messaging, etc. that are public within a group. I am really trying to wrap my head around not thinking in terms of the sql approach to this problem but I am new to NoSql so that has been a challenge.
NoSQL databases are conceptually different from relational databases in many aspects. Authorization and security in general is not their primary focus. But, most of them have evolved in that area, and they have fine-grained authorization. Basically, it depends on a particular database.
For example, Cassandra has column-level permissions in plan (https://issues.apache.org/jira/browse/CASSANDRA-12859), HBase has cell-level permissions (https://www.cloudera.com/documentation/enterprise/5-8-x/topics/cdh_sg_hbase_authorization.html). On the other hand, MongoDB is generally schemaless and it has different (more complex) document-oriented data model, which makes it hard to implement low level access control. Additionally, MongoDB has views.
So, if DBMS you are using doesn't have built-in authorization on expected level, it has to be implemented inside an application that interacts with db (if there are more than one application, things can get tricky, and some usage rules have to be established). Using denormalized models is a common thing, so different roles/groups can interact with different tables/collections which contain data that only that role/group can see (basically, it's a simulation of RDBMS views). This denormalized approach usually takes more space and it requires keeping copies in sync. If DBMS supports projection, subset of columns/fields can be presented for different roles/groups (that way, at least some of processing is done on db side).
I hope this helps, though it's a late answer.
In DDD, as far as I understand it, it helps or guides you on how to structure complex application. Now in an application, you should identify your Bounded Context. Say you have more than 10 BCs.
I read somewhere (forgive me I cannot give any links), that its not ideal to have 1-big database for a complex application. That it should be separated for each BC. If that's the easier route to take. How should one structure an app if each BC have their own database.
I tried searching on github but cannot find one.
It depends if they only share the same database or also some tables - i.e. data.
Sharing a database but not tables can be perfectly fine. Except if you aim for scalability and intend to make your BC's independently deployable and runnable units like microservices, in which case they should probably have their own data store instance.
I see a few more drawbacks to database tables shared by 2 or more Bounded Contexts :
Tight coupling. The reason we have distinct BC's is that they represent different domain spaces that are likely to diverge their own way. Changing a concept in one of the BC's might impact the underlying table, forcing the other BC's that use this table to change as well. You get rigidity where there should be suppleness. You might also have inconsistencies or "holes" in the data due to the multiple possible sources of change.
Concurrency. In highly concurrent systems, some entities and the tables underneath are subject to strong contention. Bounded Contexts are one of the ways to lighten the load by separating different types of writes, but that only works if they don't lock the same data at the end of the day. Same is true for reads in non-CQRS systems where they query the same database where writes are done.
ORM friendliness. Most ORMs won't allow you to map to 2 or more classes from the same database table without a lot of convolutions and workarounds.
How should one structure an app if each BC have their own database.
To some extent (e.g. that may include the UI layer or not), just as if you had multiple separate applications. Please be more specific if you have precise questions in mind.
The idea of having this vertical slice per bounded-context is so the relationship of each BC to every other BC and the communication between them should be considered and designed based on the domain knowledge and not on the technical merits of a persistence technology.
If you have a Customer in 2 different BCs it causes a kind-of actor pattern situation. If the Support BC needs to know about the new Customer when it is created in the Sales BC, then the Sales BC needs to connect up to a known interface on the Support BC and pass it this new information. One domain talking to another. It models quite closely how things work in real life when people from different departments talk to each other.
If you share a big database (you're talking bespoke enterprise software here so there won't be many examples in the wild) then the temptation is to bypass all the domain expertise that is captured in the domain layers and meddle in another BC's database. Things become a big ball of mud very quickly.
Surprisingly I see this sort of thing too often in the real world and I consider it very bad practice.
It depends a littlebit on the reason why they are their own database. THe idea of a bounded context is that you have a set of entities that are related together and solve a problem together. if you look at the link Chaim Eliyah provided you can have a sales and a support context.http://martinfowler.com/bliki/BoundedContext.html
Now there is no reason a product for sales,and a product for support should look the same in a database. What is important is that if support wants to add a property (say "Low quality") that it can do so while sales might not want that property. Also downtime on your sales application should probably not affect your support application.
That said entities don't care where they are stored. If you already have a huge product database you can certainly build your entities for different bounded context based on the same database. The thing to remember is that database table is not the same as entity. Entities is what your business/application needs. Database is just what's needed to store things.
That said, separate if you can. If that's not feasable try to define ownerships. You make your life a lot easier if everyone agrees that product is the product as defined by sales and that support can have a "productfactsheetTable" augmenting the product. That way you avoid conflicting changes from each bounded context. (also a followup is that support can only read products but never write). Table prefixes might help here to make this clear.
And this problem already exists with 2 related bounded context. By 10 you'll have a nightmare if multiple context try to write to the same table.
I am working on an N-tier application using .NET (C#, SQL Server). I started by designing the database because I believe starting from bottom would a good idea. Now I need your suggestions in building the database to be very flexible. Knowing that the application is intended to built as a group of plug-ins.
The application is a remote control app for many different hardware devices (Cars, Engines, etc)
Here is a fragment of the database tables.
Devices Table
Personnel Table
Users Table
Roles Table
As you can see the devices table is a table to represent the devices we are controlling and since each each device may have more or less properties than others I want to link each device to its properties which might be in another table in way that is as elegant as possible. The personnel table is for the people responsible for the device for example: Car drivers (there might be more than one driver for each car), Engine operator, etc.
Users are the application users as you can see I have separated the users and roles into two different tables.
What I am looking for is a way to link the devices to their properties. Plus, In the application each device is an instance of an attachable device. Meaning that I can attach a device called say: SIM card to a device called Vehicle. Moreover, are there any design patterns regarding this subject?
Thanks in advance, and please pardon me if I am not clear.
Depending on how you are going to be handling your data layer this database design may be a moot point. If you were to use EntityFramework with a code first approach you can create your logical entities using that and generate the database from your models.
Most ORM based solutions provide some way to create a database from your objects relationship, but although you can quickly and easily get a database up and running which will do EXACTLY what you NEED, if you want to start playing with the schema you may run into troubles, although you can do quite alot of inferring to help it make the database behind the scenes the way you want it.
If this is a greenfield project and you dont need to accommodate any legacy database system I would stop worrying about your database for the moment and just get to writing your logical models and defining their relationships, and let the data storage concerns handle themselves.
The real design decision here is around your Device and Property tables. The others are pretty standard.
For a Device to be optionally associated with one or many properties, then all you really need is a nullable foreign key in your Property table. But this raises one very important question: Is it necessary for certain devices to have a very specific set of properties? Will your application be expecting a 'Model' property for your 'Car' device? How do we ensure database integrity with this kind of design?
You can do this through database-defined constraints. But how should you know that a 'Car' device requires a 'Model' property? Perhaps you need a template definition for each device: DeviceType and PropertyType tables. This way your constraint will always know what properties are expected when you are updating/inserting a record. Also, this will make it easy to work with the data in your application.
There is no ideal database design for anything. It can quickly change according to the information you are manipulating.
One simple approach is to list all the classes in your design and then break those classes to the lowest level possible without any repeating data.
Even each device has various properties, you can classify the devices into their respective group and a group will have mostly similar properties. You can build a property table including all the properties for that group. As you said, you can connect them in a different table with deviceID and propertyID. Same thing goes for a person and device. You can break the person table into smaller pieces depending on the attributes you have.
If numerous tables form a cluster in terms of data extrection, you can consider a star schema for your solution with a fact table (real numbers) in the center and the associated data around it.
Good Luck!
First off, I am using web forms without any ORM framework.
I have been struggling with how to make my domain objects as "smart" and "rich" as they can be without allowing them access to my service and repository layer. My most recent attempt was in creating a model for gift certificates for a online store.
The main recurring issues that I am seeing is that:
More and more logic keeps being introduced in the service layer. All the calls to the repository must pass through the service layer and each time the parameters are validated (eg - exists in db, etc). As a result my service layer is growing, but my domain objects just have some simple contractual validations. Even object validation is in the service layer since if the ID of the item is null, it will check the db to ensure that the code is unique. IHMO, the consumer of the system should not care if the functionality they need deals with persistence or not.
I have a separate POCO for transaction log entries for when a gift certificate is redeemed. I assume that I should put a list or collection of these transactions as a property of my Gift Certificate model, but I am still unsure of when that property should be filled. Do I add a separate method on the service for loading the transactions into a object on demand (eg - LoadTransactions(gc object)) or should the transactions be automatically loaded any time a existing gift certificate or list of gift certificates are requested (or maybe a option in the getGCs to load transactions as well)
What about computed fields like "Available Balance"... should I even have properties like this on my object? Anytime I am working with the object, I will need to keep updating that property to insure it is up to date. Right now I simply have a service method GetBalanceByCode(gc code).
Even actions like redeeming a gift certificate are basically 100% data-centric (take some input parameters, validate them and add a transaction log entry to db).
More and more logic keeps being
introduced in the service layer (...)
Even object validation is in the
service layer (...)
Validation is not the best candidate as domain model element. Input (my personal preference is that it's represented as commands) should be validated at application service level. Domain logic should model how business work and assume that all the arguments are valid. Good candidates for domain logic are computations for example: you want to have them in one single place and have them well tested.
I have a separate POCO for transaction
log entries for when a gift
certificate is redeemed.
This kind of object is known as Event. You can learn about Events from Eric Evans 'What I learnt since the Blue Book' presentation. Event is basically an entity which is immutable. Events are quite often aggregates on their own because usually there's lots of them. By making them aggregates, you don't have any problems with lazy loading them as part of other objects's collection.
What about computed fields like
"Available Balance"... should I even
have properties like this on my
object?
Computed properties are kind of logic that naturally fits in domain model, however it's debatable if a better approach is to compute the value each time or compute it when object changes and persist it in the DB.
Even actions like redeeming a gift
certificate are basically 100%
data-centric (take some input
parameters, validate them and add a
transaction log entry to db).
This action would be modeled as creating a CertificateRedeemed event. This event would be probably created by Certificate aggregate or some other object. This blog post by Udi Dahan can be helpful
This is not an entirely easy question to answer given the fact that domain models are very subjective, and rely a lot on your...well, domain. It sounds like you are actually creating something similar to The Onion Architecture (and Part 2) described by Jeffery Palermo. This is not a bad pattern to use, though DDD purists will tell you it leads to "anemic" domain models (where your domain objects are basically Data holders with no behavior). The thing is, that may be exactly what you need in your scenario. A "full, rich" domain model may be overkill for what you are doing (and given your last bullet point it sounds like that could be the case).
You may not need a domain model for your system at all. You could be well served with some View Models (that is simple data models to describe your view) and have your UI send some DTOs to through your services to put the data in the database. If you find something that requires a more complex approach, then you can apply a richer domain model to that component. Also remember that you don't necessarily have one domain model in your system. There can, and in many cases should, be different models that describe things differently (often grouped into Bounded Contexts). The overall goal of DDD is to simplify otherwise complex systems. If its causing you additional complexity, then you may be taking the long way round.
There is an approach called DCI (data-context-interactions) which is supposed to be alternative to the old school OOP. Although it does not address explicitly the issue of persistence ignorance, your question brought it to my mind, because it deals with similar issues.
In DCI domain objects are small data-holders with only a little logic, like in your case, and interactions between them are implemented separately. The algorithm of interaction is not spread through small methods of several objects, but it is in one place, which might make it more lucid and understandable.
I think it is still rather academic thing than a solution we should start implementing tomorrow, but someone who comes across this question might be interested.