This may be a dumb question, but I don't know how to solve this.
I am moving from CRUD to Domain-Driven Design with CQRS.
I have seen many DDD examples like this. You could find many more on Github.
The domain model has methods like changeDetails, addSomething, removeSomething, etc., and the commands could be just like that.
But in the UI, I have only 1 page with all its information, and everything is updated by clicking a single Save button.
How could I trigger all of the commands in 1 click?
If all commands are triggered and 1 fails, could the information be inconsistent?
When you get to this problem, I think you need to redesign your UI and create a more task based UI, you do change one thing at the time. Just like for example when you buy something on Amazon.com, then you don't complete your order with just one big save button, instead it takes you on a journey, adding credit card details, selecting shipping, adding address, confirming the order.....
see this video Finding your service boundaries: a practical guide
Related
As my ubiquitous language I have some phrases like :
Feature : Display A Post
In order to be able to check mistakes in a post
As an admin or customer
I want to be able to view the post
Scenario : Display Post
When : I select a post
Then : the post should be viewed
Is that a right user story? Such scenarios may have some minimal differences at UI level. Should I violate the DRY principle and repeat the feature for another role?
Different users may need different requirements over time, and I think this is the reason we usually write user stories per the user role.So should I be worry about how the requirements may change over time for different roles or I can leave a single user story (and the same test code,production code, databse ...) with multiple roles and refactor when their requirements forced me to separate them ?
I am not sure what your problem here and will try to guess. So first, your first three lines is just a description and not real steps. This enables adding custom text that will not run.
As to your other 2 steps, it is very hard to say whether they are good or not. As you might have already noticed, you are not bound by Cucumber to have a specific scenario flow. Cucumber gives you the freedom to design and write your code the way it makes more sense to YOU and YOUR business logic.
Saying that, I see no issue in repeating similar steps to test another role. In order to make the feature file a bit more DRY you can use the Scenario Outline option. It might look something like this:
Scenario Outline: Display Post as <role>
When I select a post as <role>
Then the post should be viewed
Examples:
|role |
|role1|
|role2|
In this case, two scenarios run one after another while rolevalue changes according to the Examples list.
Now, in regards to your possible changes in future. You can't always predict what will happen in future and unless continuously changing current requirements is a normal practice for you or your team, I wouldn't worry too much about this. If sometime in future current scenarios will become obsolete, you will review them and rewrite them or add new ones accordingly.
If multiple roles are required in a feature, then that means it is an epic, not a feature. It is a must to break down each feature so it only has one role, and it can deliver a single value to a single group of users.
I think the problem here is your language which needs refinement to clarify what you want to do here and why its important.
It seems to me that as an admin looking to fix mistakes in a post that what I need to is to be able to change a post.
A similar thing applies for the customer (should that be author?). If you explore what they will do when a post has been authored with a mistake then you will probably find that different roles interact in different ways. You'll start to ask questions about what happens if the customer and the admin make fixes, and how the customer responds when the admin makes a fix that the customer doesn't like and all sorts of other scenarios.
If you do this you'll probably find that most of your duplication goes away, and you'll learn lots about the differences between customer and admin behaviour in this particular context.
I have a couple of questions regarding if the following process can be considered use-cases.
Website where establishments can post events.
User can "follow" establishment, "attend" event.
etc...
On my index page, i have the following sections:
Recommended Events, Events recently created, Events from establishments that the user "follows", Top 10 establishments, Recent comments, Popular events and so on.. (all which i am pulling from a database)
Would the index page be considered a use case? And would all the sections i named be individual use-cases? Considering i already have a Consult establishment, and consult event use-case, would all the section fall into this category?
I have on the establishment page a button where the user can click and the user will follow the establishment and receive notifications. All the button does once clicked, is adds the user to a table (User_Preferences), pretty much like a "like" button or a follow button.
Would this be considered a use-case(Add to Preferences use case)?
When i visit an establishment page, i am pulling data from many tables, such as: beverages, music, artists_attended, food, etc.
On the use-case Consult establishment, would i need to include every individual information? consult_beverage, consults_music,consult_artist, consult food all included to consult establishment? or are they considered already in consult establishment?
Finally, would every page i create, Index,Establishment,Events,UserProfile, etc... would they all be considered a use-case? Consult Establishment, Consult Events, Manage Profile
thank you, any tips or help would be appreciated, i understand the concept of use cases, but i sometimes tend to overthink some uses cases. thanks for the help.
The index page itself is not a use case. A use case represents some interaction between an actor and the system, but the page and its sections are part of the system design. If you were to replace the web browser with a custom-written GUI application, the use cases should be essentially the same.
In this case, you seem to be creating the use cases after you've designed the system, which is probably what's tripping you up -- use cases are usually determined before the system is designed.
"Add to Preferences" seems like a good use case. How much work goes into realizing the use case is normally of little importance; what matters is whether the interaction provides some value to the actor. The complete set of use cases describes what the user can do with the system, not how many engineering hours were spent constructing it.
You should not incorporate details on the stored data in your use cases. If you find yourself doing that you need to take a step back and try to think a little more abstractly. What does the use case do for the actor, what does the actor want? To get information about an establishment? Then that's enough, you don't need to specify the exact information stored in the system. The important thing is that the actor wants the information and that the system provides it.
Use cases are part of system analysis, not system design. As such, there is no problem with having the same design component (page) realize several use cases. So you could for instance have use cases for "see recommended events", "see coming events for 'followed' establishments", "see coming 'attended' events", all being realized in different sections on the same page.
A page is never any use case. A use case is what brings value to an actor. Simple as that. If you can name the value then you got the name of the use case. If you can't name the value then you don't have a use case.
E.g. your 1st events page: I would assume that the use case behind it will be Find Event. Similarly you have to think of the other cases. On the opposite Login to Site is not a use case because it does not bring any value to the actor.
I've been researching DDD & CQRS and I'm wondering about the correct way to present a scenario in which the application is actually being used to report what a user has already done (both in the user interface and in the command names).
Assuming I'm doing an application to track a user's activities and there are predefined set of valid activities: Swimming, Eating etc. Leaving aside the discussion about whether this domain is collaborative enough for CQRS or not (because, even if it isn't I'm sure there would be some very collaborative domains that lend themselves to similar semantic analysis), I'd like to know: On the user interface, do I present buttons that say 'Go Swimming', 'Eat' etc, with similarly named commands or do I rather use 'Report Swimming', 'Record Lunch' etc.?
The answer is in your question. I would say the clue is in how you described the application
"used to report what a user has already done"
The button's purpose will to be report a past activity so the command should be named 'Report Swimming', and the event 'Reported Swimming'.
I have faced similar scenarios and have found, 'report' commands and 'reported' events work nicely
Sounds like you are recording events. Things that have already happened and should be tracked somehow. Therefore you wouldn't send any commands at all. Just publish the respective events and handle them in your domain as needed.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
i am experiencing some difficulties(user managmen) while using selenium. It makes me start thinking about how much focused should be scenarios/steps. For example i am testing adding posts as user.
Should the user steps (Given existing user) should be clicking page to register and then add the post? Or should i create user through model and be clicking just the post addition?
Don't shame just paste a link to a short explaining article ;)
I tend to follow the approach recommended in the Cucumber Book (which I don't have to hand). Generally, it suggests using direct model access to perform setup which is not the focus of the test
e.g. for an 'adding item to my shopping basket' test, I would directly manipulate the models to create a logged-in user and products to be added, then use browser integration to perform the actions being tested, in this case clicking the 'add to basket' button and checking the basket contents.
I would only start clicking through the login page with Capybara/Webrat etc if I was actually testing the login functionality.
Find someone who is interested in the user posting the article, and talk to them about the scenarios. Whatever focus they have is probably the focus you should use.
For instance, they will probably say,
Given there's a user who likes horses
And they're already logged in
When they add a post
Then it should be visible to other people who like horses
etc.
The language is very informal. I encourage you to keep their words as much as possible. Business people definitely won't be talking in terms of clicking the post, creating user models, etc. You can make the code underneath this do whatever is necessary to make your business's scenarios work.
If something is a "Given", do whatever is easy to make it work. Maybe that's hacking data or knocking up a user model; maybe that's clicking a page. If you get it wrong you will be able to change later without changing the scenarios, so it should be OK to try whatever is easy. Automating UIs is slow, so you might eventually decide to use data or a model, but if you do this later on you'll have a better idea of what the data/model will look like anyway.
The "When" is the event that causes the behavior you're interested in - in this instance, "When they add a post". You should always do this from the highest level you can - some people like to automate the UI, others the controllers, but this is basically the core of your scenario, so you shouldn't be hacking data in here.
Here's an article I wrote about using BDD to have conversations which I think will be useful to you. You might also like this one, "Step Away from the Tools", or this rant I wrote on StackOverflow a while back.
The most important thing about BDD is to talk to people, though. Please try to do that and not let the tools prevent you from doing it!
One of the basic tenets of CQRS, as I understand it, is that commands should be behaviour-centric, and have a value in the business or the UL, and not data-centric, ie., CRUD. Instead of focusing on updating a customer, we have commands like CustomerHasMoved. What if you have CRUD screens which are there to correct certain data. For example, we need to change the name of a customer which is misspelled. This doesn't really have much value in the business. Should this just be under the umbrella of an UpdateCustomer command?
I just want to put a comment on this quickly as it popped up.
It is important to note that some objects are actually CRUD and thats ok. I may not really care why a name is changing in my domain where I ship products to people and only need that data to print mailing labels. The trick is in making behavior the default and THEN reverting to a CRUD interface once you are sure you really don't care about the reasons as opposed to vice versa.
Greg
Actually, there could be various reasons to update the name of a customer. As you were saying, it could be misspelled or... you could get married and change your name to your husband's.
If you had only an UpdateCustomer command, you would loose the original intent and you would not be able to have different behaviours for each of them. If the name was misselled it could be as simple as updating the database, whereas if your customer got married you might need to notify the marketing departement so tthat they can offer a discount.
In the case that your entity is purely CRUD, that is there is no intent that you can associate with modifying the properties, then it's OK to have an UpdateEntityCommand. You can then transition slowly to something more task based
CustomerHasMoved is the event that is fired after you have updated the customers location. This event updates the read databases/cache databases. The command from the gui should be MoveCustomer or something like that. I think I would put the update of the customer name in a command like UpdateCustomer.