Can i use two actors or more in one lane in BPMN? - business-objects

I am modeling some processes in a system and draw it in BPMN. But I confuse, can I use 2 actors in one lane? because they have the same task from start to end. they don't have differences in that business process. like the picture show. so can I? or how can I fix that?
This is the business process:

In my opinion it shouldn't be that way.
Each actor has a specific business scope if you wanna call it.
First describe best the scope of activities involved in each actor, then look of the departments interact. Wich actor has a bigger scope than the other. Why?.
Example in your case both the first actor should take care of both 2 task, and scalate them if something happen that needs a more experienced opinion. Or just if some outcome of the first task it's outside the scope of the first actor. Let's say :
First Actor takes care or approved checks up to $5000.
The first task involves putting all the details of the check as the amount.
When the first task end the outcome can be Greather/equals than $5000 or less than $5000.
Case 1 [amount < $5000]If the outcome it's less then a task for the first actor it's created when an action available it's to approve the check.
Case 2 [amount >= $5000] If the ourcome it's greather/equals then a new task it's made for the second actor, wich will require it's approvement.
Also to say in this scenario we will have 3 task, 2 for the first actor (input check task, approve low budget checks) and 1 for the second actor (approve of high budget checks).
Usually this over specification can be replaced by using some scalating mechanism. Usually involving timeframes required for the first task to be operated but it can't be based in other details too. Hope it helps . Best!

This depends a good bit on some additional context. If I were implementing this solution using a tool where the diagram is interpreted and used at runtime, my answer may be different than if I'm simply using BPMN as a good tool for capturing my Business Process.
The first question I would have if my customer modeled a process in this manner is "So, please confirm, based on this diagram, it for every instance of the process it is equally valid for either the Visitor or the Admin to execute task 1 and 2." That seems a bit unlikely to me, since based on that, any visitor could execute these tasks, no matter what their relationship to the underlying instance of the process.
For example, lets say you were capturing something where I, as the visitor should fill out a form (task 1), but you are trying to accomidate that in some situations the Admin might fill out the form for me. If makes sense that either I can fill out the form for myself, or the Admin can, but it doesn't make sense that you, a person totally unrelated to me and not an Admin, would be allowed to fill out the form.
If I were modeling the above scenario (who fills out the form) I would likely have a decision gateway after the start that would evaluate "Is Andrew going to do this?". A yes would go to "Fill out form" activity for me, and a "No" would route to the "Fill out form" for the Admin.
As in many things in life, there isn't a clear answer, especially when the thing you have asked is so abstract. I can come up with examples where either model is valid, but would need the specifics to get it right.

Related

Database design & normalization

I'm creating a messaging system for a e-learning platform and there are some design concerns that I'd like some feedback on.
First of all, it is important for me and my system to be highly modifiable in the future. As such, maintaining a fairly high normalization across my tables is important.
On to how my system will work:
All members (students or teachers) are part of a virtual classroom.
Teachers can create tasks and exercises in these classrooms and assign them to one or multiple students (member_task table not illustrated).
A student can request help for a specific task or exercise by sending a message to the teachers of the classroom.
Messages sent by students are sent to all the teachers. They cannot address a message to a specific teacher.
Messages sent by teachers can be addressed to one or more students.
Students cannot send messages to other students.
Messages behave like chat, meaning that a private conversation starts between a student and all teachers when they send a message.
Here's the ER diagram I made:
So my question is, is this table normalized properly for my purpose? Is there anything that can be done to reduce redundancy of data across my tables? And out of curiosity, is it in BCNF?
Another question: I don't intend to ever implement delete features anywhere in my system. Only "archiving" where said classroom/task/member/message/whatever is simply hidden/deactivated. So is there any reason to actually use FK?
EDIT: Also, a friend brought to my attention that the Conversations table might be redundant, and it kinda feels so. Thoughts?
Thanks.
In response to your emphasis on "modifiability" which I'm taking to mean with respect to application and schema evolution I'm actually going to suggest a fairly extreme solution. Before that some notes some aspects you've mentioned. First, foreign keys represent meaningful constraints in your data. They should always be defined and enforced. Foreign keys are not there just for cascading delete. Second, the Conversations table is arguably redundant. It would make sense if you had a notion of "session" of chat which would correspond to a Conversation. Otherwise, you just have a bunch of messages throughout time. The Conversation table could also enable a many-to-many relation between messages and tasks/exercises if you wanted to have chats that simultaneously covered multiple exercises, for example.
Now for the extreme suggestion. You could use 6NF. In particular, you might look at its incarnation in anchor modeling. The most notable difference in this approach is each attribute is modeled as a different table. 6NF supports temporal databases (supported in anchor modeling via "historized" attributes/ties). This means handling situations like a student being associated to a task now but not later won't cause all their messages to disappear. Most relevant to you, all schema modifications are non-destructive and additive, so no old code breaks when you make a change.
There are downsides. First, it's a bit weird, and in particular anchor modeling (somewhat gratuitously?) introduces a bunch of new terms. Second, it produces weird queries for most relational databases which they may not optimize well. This can sometimes be resolved with materialized views. Third, at the physical level, every attribute is effectively nullable. Finally, the tooling and support, while present, is pretty young. In particular, for MySQL, you may only be "inspired by" what's provided on the anchor modeling site.
As far as the actual database model would go, it would look roughly similar. Anchor modeling uses the term "anchor" for roughly the same thing as an entity, and "tie" for roughly the same thing as a relation. For simplicity, dropping the Conversation relation (and thus directly connecting Message to Task), the image would be similar: you'd have an anchor for Classroom, Member, Message, and Task, and a tie replacing Recipient that you might called ReceivedMessage representing the relation of "member received message message". The attributes on your entities would be attribute nodes. Making the message attribute on the Message anchor historized would allow messages to be edited if desired and support a history of revisions.
One concern I have is that I don't see a Users table which will hold all the students and teachers info (login, email, system id, role, etc) but I assume there is something similar in our system?
Now, looking into the Members table: usually students change classes every semester or so and you don't want last semesters' students to receive new messages. I would suggest the following:
Members
=============
PK member_id
FK class_id
FK user_id
--------------
join_date
leave_date
active
role
The last two fields might be redundant:
active: is an alternative solution if you want to avoid using dates. This will become false when a user stops being member of this class. Since there is not delete feature, the Members entry has to be preserved for archive purposes (and historical log).
role: Depends on how you setup Users table and roles in your system. If a user entry has role field(s) then this is not needed. However, this field allows for the same user to assume different roles in different classes. Example: a 3rd year student, who was a member of this class 2 years ago, is now working as TA/LA (teaching/lab assistant) for the same class. This depends on how the institution works... in my BSc we had the "rule": anyone with grade > 8.5/10 in Java could volunteer to do workshops to other students (using uni's labs). Finally, this field if used as a mask or a constant, allows for roles to be extended (future-proof)
As for FKs I will always suggest using them for data consistency. Things can get really ugly really fast without FKs. The limitations they impose can be worked around and they are usually needed: What is the purpose of archiving a message with sender_id if the sender has been deleted by accident? Also, note that in most systems FKs are indexed which improves the performance of queries/joins.
Hope the above helps and not confuse things :)

can a PORO access the database?

as my first Rails app, I am building a homework management app which has these tables:
users (from Devise authentication)
schools
courses
assignments
Unlike most examples of course/grading apps I've found, this one is never concerned with all the grades for all students for a particular course, but has only a 1:many relationship between student and courses. So the examples don't really help me.
In order to calculate a user's current grade in any given course (which requires access to data in both course model and assignment model), I am following a suggestion from here on Stack Overflow and creating a PORO in the app/models directory called GradeCalculator.
But this is my first experience with building a PORO into a Rails app, and most of the documentation I'm finding online is for more sophisticated users. I'm assuming it doesn't need a controller (please correct me if I'm wrong), and I see that building it is as simple as:
app/models/gradecalculator.rb
Class GradeCalculator
def calculate_current_course_grade(course_id)
#graded_course_assignments = Assignment.where(user_id: current_user.id, course_id: course_id, graded: true)
#grab weights for each type of assignment in #graded_course_assignments from courses table
#do some calculations
#return the array
end
def calculate_user_GPA(current_user.id)
#more of the same
end
end
My questions are:
Can a PORO access the database (to get data from the courses and assignments tables). Or do I need to pass it all the relevant data from my other classes (like assignments) as params when calling it?
1a. If a simple class can access the database, does the syntax differ from that in the models? Would the above code be able to access Assignment.where?
1b. How would I call this PORO? For example, how would I call it from my views/assignments/index.html.erb?
Can it access Devise's current_user helper?
Tangentially, I just realized that I could store assignment weights in the assigments table. I was thinking chronologically (user inputs number of homework assignments, quizes, etc. at the time of inputting a new course, which determines the weight for each type of assignment), but I could programmatically have each new assignment populate its own weight field by referencing the number of like assignments from its parent course. This would mean, logically, I could do the grade calculation right in the Assignment model. But if extra credit or other changes were added to the course, all the assignments might then have to recalculate their weights. Which way is more correct?
Writing these questions makes me suspect that I am just to pass my PORO the relevant data from my view, let it do calculations on that data and return a grade. But I will post anyway, just in case I'm wrong.
The reason for breaking business logic out into POROs like this is usually to make your code easier to reason about and easier (and faster) to test. To that end, you do not want GradeCalculator to know or care how Assignment works. You should just pass GradeCalculator all of the data it needs (or a Relation, which quacks like an Enumerable). Having GradeCalculator call Assignment.where means that your tests will depend on ActiveRecord, and the database, which means they'll be slow. If GradeCalculator just expects an array, in your tests you'll just have to mock an array of objects that respond to whatever attribute methods GradeCalculator needs to know about, and you'll be able to run them without loading Rails at all. (It's common to have a separate spec_helper.rb and rails_helper.rb so that specs that don't need Rails can run without loading Rails, which makes them so much faster.)
Per your second question my advice is similar: Decouple your POROs as much as possible from Rails and from Devise.

web inserts at the same time

We have developed an online quiz where users can register a team to take part in the quiz.
There is a check in the asp to see if that teamname has already been submitted, and if it has, an error is generated.
We have noticed a problem if 2 teams are registered at exactly the same time with the same name, that both teams are registered. Although this is highly unlikely, we wondered what approach should be used to overcome this.
We are using mySql as the database if that makes any difference.
Thanks for any guidance.
Don't worry this never happens.
Databases are smart enough and handle concurrency isuuses.
If you run a query on database for registering a team and another team register at the same time, at database level the first query (when it's send to database) succeed and the second fails with an error which you should take care of. If registeration needs actions more than a simple insert on a table then you should use transaction objects at your queries/store-procedures.
You can set the name column to be unique, and the database will throw an error on the second insert. If you want to do it in code, it will be more complicated.
Not sure how two teams can register at exactly the same time - even if the requests are submitted simultaneously (down to the nanosecond), your transaction semantics should still guarantee that one of them is "first" from the database point of view.

Keeping Drop-downs DRY in a web app

I'm writing a CMS for various forms and such, and I find I'm creating a lot of drop-downs. I don't really feel like mucking up my database with tons of random key/string value tables for simple drop-downs with 2-4 options that change very infrequently. What do you do to manage this in a responsible way?
This is language-agnostic, but I'm working in Rails, if anyone has specific advice.
We put everything into a single LookUp table in the database, with a column that mapped to an enum that described which lookup it was for (title, country, etc.).
This enabled us to add the flexibility of an "Other, please specify" option in lookup dropdowns. We made a control that encapsulated this, with a property to turn this behaviour on or off on a case-by-case basis.
If the end user picked "Other, please specify", a textbox would appear for them to enter their own value. This would be added to the lookup table, but flagged as an ad hoc item.
The table contained a flag denoting the status of each lookup value: Active, Inactive, AdHoc. Only Active ones would appear in the dropdown; AdHoc ones were those created via the "Other, please specify" option.
An admin page showed the frequency of usage of the AdHoc values, allowing the administrators of the site to promote common popular values into general usage (i.e. changing their Status flag to Active).
This may well be overkill for your app, but it worked really well for ours: the app was basically almost entirely CRUD operations on very business-specific data. We had dozens of lookups throughout the site that the customer wanted to be able to maintain themselves. This gave them total flexibility with no intervention from us.
You cold have one single dropdown table with an extra column to say what the drop down is for... limit the results with a where clause...
At my current position, we implemented a LookupCode table that contains a CodeGroup,Code, and Meaning column, as well as some others (like active). That way you have a single table that contains all of your lookup values are in a single location and you can do some quick lookups to bind to your dropdown lists.

Techniques for adding Achievements to business class software

I was thinking of adding some Achievements to our internal bug-tracking and time logging system. It's connected to an SQL Server back-end.
At first I thought that the system could be run on the database, using triggers to, for example, know when:
you've logged 1000 hours
created 1000 tickets
closed your own ticket
worked on a ticket that has been not touched in a while.
etc (you know - database-ish things)
But then I realized that I would also want purely front-end achivements
used the advanced search abiltiy
sorted by a column
reset settings to default
searched 500 times
It seems like the logic of every achievement must be hand coded. Could anyone imagine an some sort of Achievements Rules Engine, that you for example create scripts for?
And how to store them? If the achievement is:
change column sort order 50 times in one session
that would imply that every time they sort a listview column it updates the database.
Any thoughts on this Win32 application design problem? I don't think that the Gang of Four have an Achievements design pattern.
Note: It's a Win32 client application, not a web-site.
i definetly like the idea of an eventing system. Various actions the user takes can raise events through a single eventing object:
protected void TimeEntriesListView_ColumnSort(object sender, EventArgs e)
{
_globalListener.RaiseEvent(EventType.ListViewColumnSort, sender, e);
}
protected void TimeEntriesListView_ColumnDrag(object sender, EventArgs e)
{
_globalListener.RaiseEvent(EventType.ListViewColumnDrag, sender, e);
}
That object can then have logic added to it to decide which events it wants to count. But more reasonably, various event listeners can attached to the central event listener, and have their custom achievement logic.
The trick isn't the coding of the rules, really, those are straightforward, and can perhaps be simple expressions (number_of_bugs > 1000).
The trick is accumulating the statistics. You should look at a form of Event Stream Processing to record your achievements. For example, you don't really want to implement the "1000 bugs" achievement with "select count(*) from bugs where user= :user" all the time (you could do it this way, but arguably shouldn't). Rather you should get an event every time they post a bug, and you achievement system records "found another bug". Then the rule can check the "number_of_bugs > 1000".
Obviously you may need to "prime the pump" so to speak, setting the number_of_bugs to the current number in the DB when you start the achievement system up.
But the goal is to keep the actual event processing light weight, so let it track the events as they go by with all of the events running on a common, internal pipe or bus.
A scripting language is a good idea as well, as they can easily evaluate both expressions and more complicated logic. "number_of_bugs > 1000" is a perfectly valid Javascript program for example. The game is just getting the environment set up.
You can also store the scripts in the DB and make an "achievement" editor to add them on the fly if you like, assuming you're capturing all of the relevant events.
I am also trying to figure out how to build an achievements rules engine.
I checked around rules engines and what are the basics of it. There is a good summary of that in wikipedia
Basically, you either have foward chaining when you, for example, check availability for something; otherwise, you use Event Condition Action rules. Its the latest that caught my attention.
So you could predefine a set of triggered events. In the engine you can define what are the checked conditions who are based on available metrics, and specify the association achievement.
This way seems more flexible, but you have to define the events, possible condition checks and metrics.
For example, you would have various events like TicketCreated triggered in the code.
In the rule engine you could have something like
Event: TicketCreated
Condition: UserTicketCount >= 1000
Achivement: "Created 1000 tickets"
or for "reset settings to default"
Event: SettingsChanged
Condition: Settings = DEFAULT
Achievement: "Reset to Default"
I haven't tried it yet, but I'm going to pretty soon. It's mostly theoric for now.
The backend achievements should be simple - they seem to be based on already tracked items. The front end, as you correctly stated, will require more tracking. One way you might want to do this is implement an analytics engine for your front end site.
Piwik at http://www.piwik.org might help here - it is a google analytics clone, that you host yourself. The idea would be to use it's logging capabilities to track when an achievement has been completed.
As for some form of scripting of the rules, you will always have to hand code them - you can perhaps make it simpler though, by creating your own small scripting engine, or implementing a custom Lua set.
How about storing the sql query associated with the achievement in the database itself, so adding a new achievement would only involve adding the name and the sql query for it.
for e.g.
you've logged 1000 hours - "select case sum(hours) > 1000 then 'true' else ' false' end from user where user_id = ?"
The UI based achievements would have to have the data stored in the db as well because you may use the same data for other achievements going forward.
I think one table to hold each event that you want to track. Such as "Performed a search". Then each achievement could have an SQL associated with it.
You could then build one trigger, on the Event table, which would compare the achievements that apply to that event, and add the achievement to the Achivement table.
Here are the quickie table designs:
EventItems:
UserId, EventName, DateOccured, AnyOtherInfo
AchievementQualifiers:
Achievement Name, AchievementCheckSQL, EventsThisAppliesTo
(Normalize this, if multiple events apply)
In you System, weather its web or win32, you simply insert into the EventItems table whenever the user does some event that you want to track. You could make one class to handle this. For purely DB type events, such as "Item Posted" or "Comment Posted" you could do this with a trigger instead.
Then, in the triggers on EventItems, for each AchievementQualifer that has that EventThisAppliesTo, run the SQL check, and update an UserAchievement table if it's true and hasn't been awarded yet.
Excuse my spelling, as I'm typing this while sitting in a brew pub.