Suppose I have a use case buy book, and the main flow is the following:
1- The user types the book code that he wants to buy
2- The system replies that there's enough stock of the requested book
3- The user confirm
Very simple.
Now suppose I want to give the option to the user to also do another thing between 2 and 3. How should I say it? I guess it's an extension to this use case, but I'm not sure where it's the point of extension.
As far as I know, if I choose, say, point of extension in 3, then the user has the opportunity to do 3 or do all the extension but not 3. The same behaviour of alternative flows.
But what I want is different. I want some "2.5" or nothing... do it or do nothing instead; not another thing.
I'm sorry for the vague question.
One option is the format recommended in Alistair Cockburn's Writing Effective Use Cases:
2a- User wants to do another thing:
2a1- The user does another thing
2a2- The system responds in some way, returns to step 3
Step 2a occurs after step 2 and before step 3. If the UC ends at step 2a2 then simply replace 'returns to step 3' with 'Use Case ends' or similar.
hth.
The problem here is the difference between the use case model in UML and use case descriptions. Extensions point is a concept from UML used to decouple extended and extending use cases. If you want adhere to this, you have to define the position of branching and returning back yourself, because UML says nothing about use case descriptions. I am personally as well as sfinnie a fan of Alistair Cockburns's approach to use cases, however it does not correspond well with the UML standard. There is yet another way, proposed by Bittner (Use case modeling book), who proposes to split the scenario into subflows with headlines.
I think what you actually want is an alternate path. An alternate path references a step in the main or in a different alternate path. I usually make that reference the Start step in the alternate. Then the End step is either a reference to where it returns to or an indication the path stops.
Related
I am automating a system using BDD with Serenity + Cucumber-jvm, and I have some cases, that the same step can be used as any keyword step definition.
Example:
Given something
When do something
Then other thing
And do something
As you can see, do something is used with both when and then, but If I define the same method with these 2 annotations:
#When("do something")
#Then("do something")
public void doSomething() {
}
I get the following error:
cucumber.runtime.DuplicateStepDefinitionException: Duplicate step definitions in ...
How do I resolve this issue
"Given" describes the context in which the scenario takes place. It either describes a state, or it describes something that has happened. So phrase it in either the continuous present, or the past tense.
Given the invoice is two weeks late <-- continuous present
Given the invoice was submitted <-- past
You'll also notice that it doesn't say anything about who submitted the invoice. That's fine for the context, because it doesn't matter how it got there. We call this the "passive" as opposed to the "active" voice.
"When" describes an event that happens. I like to put this in the present tense, active voice. "The dog bit the boy" is active voice. "The boy was bitten" is passive since it doesn't mention who did it. By mentioning who does it, we remind people that there's a user involved, even if that user is another system.
When I check my accounts
When the admin creates a new record
When the ETL begins
"Then" describes what ought to happen, in that context, for that event. I like to use the word "should", which is a conditional tense. It's also in the passive voice because the "when" should cover how it happened.
Then the invoice should be marked as paid
Then I should receive an email <-- "I" am not the doer so this is still passive voice
The word "should" has an additional benefit. Back in the days of Waterfall development, we used to try to get all the requirements right, but we never quite managed it.
By using the word "should", we encapsulate the idea that uncertainty still exists. It encourages people to question whether the requirements are accurate, and in the face of changing technology and innovation, whether they're still accurate. It's easier to change an idea when it isn't using "must" or "will", as those are words which express certainty, and if you're convinced that someone else is certain about something, you're less likely to push back.
By pushing back and making other suggestions we get "exploration by example", and it's the precursor to specification or test by example, which are nice by-products. Ideally you'll be talking through more scenarios than you actually keep, and deciding which ones are in and out of scope. The word "should" really helps with that, and keeping it when you capture those scenarios and write them down helps too.
And, of course, it helps to differentiate "Given" and "Then" (but hopefully not "When" since that will be phrased in the active voice anyway).
So, if I were to use your "do something" example, I might say:
Given something was done
When someone does something
Then something else should have happened.
Now none of your scenario steps are similar, and you've clarified what you really mean by them, too.
I wrote a blog post on this a while back if it helps as a reference.
For Cucumber The keyword in front a step definition (Given,When,Then,And..) does not make any difference it is for lexical clarity and beauty. That said when you do
#When("do something")
#Then("do something")
is equivalent to:
#When("do something")
#When("do something")
or
#Then("do something")
#Then("do something")
So not to get duplicate step definitions you need just to look at the text not the keyword :)
I've got a need where each user can customize their own page on a replicated site. In grails it seems the most straightforward way to do this is:
somedomain.com/someController/JohnDoe
spelling out a controller, except this forces folks to type in a longer domain name, versus something like
somedomain.com/JohnDoe
Using sub-domains may be another approach, however they would need to be created automatically, i.e. when someone joins.
Can you please clarify the main ways Grails supports this kind of requirement/need (replicated site), and some of the pros/cons of each?
Thanks, Ray
Edit: Per Tomasz's edit below, the simplest course of action isn't clear. If you have insights on this please do share.
It is called UrlMappings in grails. You need to declare:
"/$username?" {
controller = 'someController'
action = 'user'
}
It redirects to someController, action user and optional variable called username.
This solution has one catch. Every one level path you visit passes this rule and takes you to someController. You cannot go to somedomain.com/books because it passes rule above and it follows you to someController#user with params['username']='books'. Then you can't use default actions. But if you decide that all your other paths have at least one slash, e.g. /books/list then you can follow this solution
Edit: I was wrong. It doesn't work as I've expected. I thought that UrlMappings are applied in order they are defined. That's not true, as explained here. Even worse - it's not documented (GRAILS-6246). Most specific explanation comes from Peter Ledbrook :
It uses a specificity algorithm, so the most specific match should apply
You must experiment then. I suggest you use safest solution and stick with /user/username solution.
The auto_complete_for dealio from script.aculo.us is great an all, but is there a way for me to selectively disable the fact that it always auto-selects the first item in the list?
The problem is that, if I want to type my own entry that is new, and novel, I don't want the first item in the list to be auto-selected. The reason is because when I TAB out of the field, it selects, and fills the text box with that first item.
I got around that, somewhat, by making the first item in the list the same as what I'm typing, but that's not perfect either, because the auto_complete list doesn't always update with every keystroke, depending on how fast I type. I've tried setting the list refresh rate to the lowest value (1 millisecond) but no go.
What I really want is an option in "auto_complete_for" that doesn't select that first item at all - the same way that Google Instant doesn't automatically select the first suggested search phrase - you have to arrow-down to select one.
Maybe I can do this via an HTML option that I'm missing?
Looking at the source, there doesn't appear to be an option for that, but I bet if you changed line 284 of controls.js to this.index = -1; it would do what you want.
Otherwise, it might be time to look for a different autocomplete widget.
If your requirements are too far away from the available plugin, then I guess there is no point in tinkering around. Its best to write your own JS code.
You might want to consider this: https://github.com/laktek/jQuery-Smart-Auto-Complete
or this : https://github.com/reinh/jquery-autocomplete
I'll add another alternative that works great with Rails 3:
http://github.com/crowdint/rails3-jquery-autocomplete
I recently implemented auto complete for more than a field for Rails 2.0.2.
The plugin I used is:- https://github.com/david-kerins/auto_complete . Not sure if it supports Rails 3.
I have also encountered issues on implementing the above scenario and have posted questions( Implementing auto complete for more than one field in Rails ; Implementing a OnClick kind of functionality and formatting wrt Rails Partial-Views ) on stackoverflow for the same, I have been lucky on getting things working for me based on my requirement.
Kindly refer to these questions, they might have relevance to your requirement.
I'm building a site that shows changes in deals that we have in our db. For example, if a deals status changes from pending to win, I want to show it, and if the value goes up or down, I want to show it, that kind of thing. Also, if you open the overview page, I want it to show the history of changes. So I need some kind of change logging, to be able to look in the past. How do I do this?
It is a rails project, but I think that's irrelevant.
I doubt there is any generic solution to this problem.
You can roll out your own. Start by considering all objects that need change logging. How many types are there? How often do you expect changes to occur? This will help you estimate the potential number of changes throughput you'll need to be dealing with. If there aren't too many, just stick them into database. If you are generating a lot, try storing to comma-separated-value file.
I have implemented a similar system before. I had 3 types of changes: 1) property value change, 2) adding of a value to a list, 3) removing value from a list.
I used the following format, stored in a log file:
//For type 1)
1,2011/01/01 00:00:00,MyObject,myProperty,oldValue,newValue
//For type 2)
2,2011/01/01 00:00:00,MyObject,myListProperty,addedValue
//For type 3)
3,2011/01/01 00:00:00,MyObject,myListProperty,removedValue
This captured most information I needed. The value parts were just some user-readable summary of the changed/added/removed property value.
Paper Trail Gem
Since you're on Rails, take a look at the PaperTrail gem. It does exactly what you're looking for and is beautifully built. You'll just need to add in a callback so that your overview page knows that a change occurred. But for the history of a model, just use the built-in PaperTrail functionality.
This is a new application, and I have an index method on a Search controller. This also serves as the home page for the application, and I'm trying to decide if I am headed down the wrong path from a design pattern perspective.
The method is already 35 lines long. Here is what the method does:
3 lines of setting variables to determine what "level" of hierarchical data is being searched.
Another 10 lines to populate some view variables based on whether a subdomain was in the request or not.
A 10 line section to redirect to one of two pages based on:
1) If the user does not have access, and is signed in, and has not yet requested access, tell them "click here to request access to this brand".
2) If the user does not have access, is signed in, and has already requested access, tell them "so and so is reviewing your request".
Another 10 lines to build the dynamic arel.
I can't get it straight in my head how to separate these concerns, or even if they should be separated. I appreciate any help you can offer!
Summarizing what you've said in something codelike (sorry, don't know ruby; consider it pseudocode):
void index() {
establishHierarchyLevel();
if (requestIncludedSubdomain())
fillSubdomainFields();
else
fillNonsubdomainFields();
if (user.isSignedIn() && !user.hasAccess()) {
if (user.hasRequestedAccess())
letUserIn();
else
adviseUserOfRequestUnderReview();
}
buildDynamicArelWhateverThatIs();
}
14 lines instead of 35 (of course, the bodies of the extracted methods will lengthen the overall code, but you can look at this and know what it's doing). Is it worth doing? That really depends on whether it's clearer to you or subsequent programmers. My guess is it's worth doing, that splitting out little code blocks into their own method will make the code easier to maintain.
That's a lot of variables being set. Maybe this is a good opportunity for a module of some kind? Perhaps your module can make a lot of these decisions for you, as well as acting as a wrapper for a lot of these variables. Sorry I don't have a more specific answer.
Without your code it's somewhat difficult to suggest actual fixes, but it definitely sounds like a really wrong approach and that you're making things much harder than they need to be:
3 lines of setting variables to
determine what "level" of hierarchical
data is being searched
if there is a search form, I would think you would want to pass those straight from the params hash into scopes or Model.where() calls. Setup scopes on your model as appropriate.
Another 10 lines to populate some view variables based on whether a subdomain was in the request or not.
This seems to me like it should be at most 1 line. or that in your view, you should use if statements to change what you'd like your output to be depending on your subdomain.
A 10 line section to redirect to one of two pages based on:
the only thing different in your explanation of the 2 views is "whether the user has requested access" surely this is just a boolean variable? You only need 1 view. Wrap the differences into 2 partials and then in your view and write one if statement to choose between them.
Another 10 lines to build the dynamic arel.
It might be necessary to go into Arel, but I highly highly doubt it. Your actual search call can in most cases (and should aim to be) 1 line, done through the standard ActiveRecord query interface. You want to setup strong scopes in your models that take care of joining to other models/narrowing conditions, etc. through the ActiveRecord Query interface.