EPICS


Development and EPICS and Howto and Ideas and Opinion19 Mar 2008 09:45 am

As the Active Record class has become increasingly popular due to it’s wild success in Ruby on Rails, it seems as though every framework has an implementation of it. It is no surprise that inside the covers of the MyEPICS framework lives an active record class that I had created. This class has evolved and changed over time, which I am going to share my experiences writing it. It is far from finished, but it has been quite a great learning experience along the way.

2.0 Implementation

The MyEPICS 2.0 implementation contained one master database class (ME_DB) which contained generic CRUD functions, and each table contained its own class which would implement the specific CRUD functions for each table (ME_DBO). A sample way to read users with the name ‘bob’ would be the following:

$user=new ME_DBO_User();
$user->read(array('name'=>'bob'));

And to update a person’s last name to “foobar”, you would do the following:

$user->lastname="foobar";
$user->update();

About 90% of each of the ME_DBO classes were the same code, and there was even a script to create a DBO class given a SQL create statement. A major problem with this approach is that for every new table created, you needed to make sure you created a new ME_DBO file, and that the file really only contained such things as which columns were in the table and their default values. We would have about 2k lines of code between 30 files, of which only about 50 lines were different… YUCK! Over Christmas break, I decided that this was a major, major issue that needed to be worked out before MyEPICS 2.1.

MyEPICS 2.1 Implementation

With the 2.1 implementation, I took a step back and attempted to create two classes which would fix the pitfalls of the 2.0 implementation. What I ended up doing was using MBD2’s reverse engineering module in order to find out which fields were available and what their default values were. This reduced the need for a separate file for each table and removed about 1500 lines of code from the Active Record implementation. Now, instead of

$user=new ME_DBO_User();

You would do this instead

$user=ME_Db::factory('User');

This has the main database create a Dbo object with just the right properties that you need.

The only major gripe I have with the current implementation is that I don’t implement anything for relationships. If you need information from a relationship, then you have three options.

  1. Cry
  2. Write Manual SQL
  3. Write many lines of code which does a lot of extra sql queries and is inefficient and crappy

I mainly want to create something so that the relationship table is transparent. A lot of the time, your relationship table doesn’t have anything of value in it, and it only exists for a many to many relationship.

SQL Command Functions

About

One such feature that I see in a lot of Active Record implementations is the ability to use functions named after SQL commands, such as:

$db=new Some_Active_Record_Class();
$db->select('firstname')->from('User')->where('id=5');

Mostly, I had disregarded this need in my Active Record implementation because it seemed like it was a lot of work for very little gain. Why would you need to allow such functionality when creating a simple sql statement would do?

Well, I think I had just stumbled upon the reason for its need.

The Problem

I have a class for a user and contains information pertaining to the user such as first name, last name, e-mail address etc… It has some very useful functions such as getUserWithRole($role) and getPriviliges($user). What I need to be able to do, is extend this information through one of the MyEPICS modules. Such an example is in my Roommate Finder application, which extends the user to give them traits. The user module does not know about the Roommate Finder application, nor should it have to. Now, here’s the problem. What I need to be able to do, is return a result set of all the users’ traits, where the user has a certain role. I already have the code to return all users with a certain role in the Users module, now I just need to attach the trait information to the output of it.

I have come up with a few different solutions that would plug this hole, but not fix the problem, with most of them being some variation of typing up a single sql statement to get me the information. What I don’t want to do, is getUsersWithRole(), then iterate through all of theses picking out the traits for each individual user. This would result in at least one sql statement per user, which is highly innefficient.

I want to be able to execute this functionality in one sql query, without having to tightly couple the User module with the Roommate Finder module, and without duplicating functionality already existing in the User module.

A Solution?

What I have been thinking about that would solve this problem would end up having me creating something like the database command functions. Then, what the getUserWithRoel() function would do, is instead of returning the results, it would return a Dbo object with the sql already added. So that if getUsersWithRole() would normally result in some query like “select role from roles where role=?”, then it would now return an object that represents this statement. What this would allow me to do is chain these functions together, then only execute the query at the end. For example:

//fetch results in an array
$dbo=$userModule->withRole('Tenant')->join('Traits')->fetchArray();

This has several features which I haven’t implemented. Easy relationships, chaining of functions, and the sql commands.

Is it bad that I am never satisfied with what I already have, and always want to refactor to make it better?

EPICS28 Oct 2007 06:44 am

As I have talked about Ohloh.net earlier, I submitted the MyEPICS project to the site for fun. What I got back was that the MyEPICS 2 project was valued at over $1,000,000 dollars and would take approximately 19 person years to develop. Amazing!

Development and EPICS and Howto22 Oct 2007 08:07 pm

So I have been doing some more Gnary Queries for MyEPICS.

We have a table called TeamChoice that has 3 columns, userid, teamid, and choice. These represent a person’s 5 choices that they make when registering for EPICS. There is one special row for each person. If the person is not assigned to a team, they are given a choice=0 with their current team choice. So with 5 team choices, each user has 6 rows in the database.

The Scenario

What I wanted to do is find all the students who are currently in their first team’s bucket. So that means that for each user, I wanted to get the teamid where choice=0, and compare it to where choice=1. If they are the same teamid, I wanted to return the result. This probably could be accomplished by some script, but a database should be able to give me the results w/o any scripting.

The Method

The way to accomplish this is through subqueries. I realized that I am essentially querying against two tables, then doing a join on the userid. The first table all the records for students and their first choice, the second table is the records for students and their current choice. If I then join the two tables together on their userid, then I will have what their first choice is, and their current choice. All I need to do next is add a where clause that makes sure that I only get records with the two results are the same and it’s over.

The Query

SELECT User.username
FROM (
SELECT TeamChoice. *
FROM User
INNER JOIN TeamChoice ON User.id = TeamChoice.userid
WHERE TeamChoice.choice =1
) AS firstchoice
INNER JOIN (
SELECT TeamChoice. *
FROM User
INNER JOIN TeamChoice ON User.id = TeamChoice.userid
WHERE TeamChoice.choice =0
) AS currentchoice
ON currentchoice.userid = firstchoice.userid
INNER JOIN User ON User.id = currentchoice.userid
WHERE firstchoice.teamid = currentchoice.teamid
Development and EPICS and Howto17 Jun 2007 11:47 pm

I have been working on the MyEPICS 2.0 framework for creating a website to match roommates together. During this time, I was switching from the old layout, to a different look and feel. When the designing and implementing the MyEPICS framework, I tried to make it as modular as possible, and able to switch layouts easily.

The only big problem that I ran across was empty div tags. The author of the article does a good job of explaining exactly what happened, but doesn’t offer a solution. He may have lost 2 hours of his life finding the problem, but I lost 2 hours of my life attempting to find a solution. My solution was to add an <xsl:output> tag to my XSLT sheet, with a method of ‘html’, which then properly fixed the problem. No more were empty div tags consuming whatever was after them, and it adds a DOCTYPE declaration, which is a big bonus! Now the output passes xhtml strict.

Development and EPICS and Howto and Opinion14 May 2007 07:39 pm

I have been working with SVN for the better part of around two years, and let me say, it is wonderful! When I first started to learn about version control, I tried to learn with THE standard, CVS. Well, a new player had made its way into the hearts of many developers, and Dan turned me onto it. What was it? It was Subversion. I won’t go into many of the details that made CVS different from SVN, but let me say that it allowed me to understand version control much better than I did with CVS.

If you are familiar with what a tag and what a branch is, you can skip the next couple of paragraphs. If not, read on for my explanation of what they are.

A tag is basically a snapshot of your code at a specific point in place. You don’t make any updates to a tag, you really only use it as reference. Why would you want to do something like this? Well, mostly it is for historical reasons. Whenever you release a new version of your code, you want to tag it so that you can always check out that version w/o having to remember the version number. In SVN a tag is basically just a label for a specific version of the repository, but labeling things is important.

Branches on the other hand are a bit more involved. The standard way of explaining tags is saying that it is parallel development of your code. What exactly does this mean though? Well, you can imagine that you want to release your code at some point in the future (if not, then reread this sentence until it is a true statement). You have features X, Y and Z that are being developed and you want version 1.0 to contain these features. Well, what happens if there is feature Q that is slated to be in 2.0, but you want to start developing it now? Well, what is normally done is that you can make a branch. Usually, new development is done in the trunk, so you would branch off the 1.0 code. At this point, you will now have two developments of your code. You will have your 1.0 branch to contain X, Y, and Z, and you will have the trunk (2.0) to contain Q, X, Y, and Z. You do all development in your trunk (i.e. 2.0), and anything that you want to release into 1.0, you merge from the trunk, into the 1.0 branch.

When you begin the development of your application, tags and branches will not be necessary. Every part of development will belong in the trunk and will most likely stay there until you have some initial release of the code. From that initial release will all of this complexity start to make sense. Believe me, it took me the better part of 6 months to finally understand the whole need for tags and branches beyond the standard examples given to you from Alice and Bob.

Ok, got the idea of tags and branches? Good!

In MyEPICS, we are just now getting ready to upload the code onto SourceForge. One of the topics that came up (or I brought up) was how to mange the version numbers of the code. I want the actual version number to mean something. When developing this idea, I had borrowed quite a bit from PHP. They have X.Y.Z, where X=Major, Y=Minor and Z=Release. I would think that MyEPICS can borrow from this idea to also have a X.Y[.Z] where Z is optional. X is the major release. The decision to bump up the major release would be done through decisions of what features will be implemented. As of right now, I cannot see anything that is slated would have a major number increase (mainly because of the differences between 1.0 and 2.0, which were pretty vast).

A minor release can contain such things as the addition of one or many modules and any features that aren’t too intense of a change.

As I see it, all bug fixes that are released will go into a “Release” release. I think it would be good to call it a bug release.

As this gets more set in stone I will keep all of this updated.

Buy fake rolex watch for sale replica watches replica rolex womens. Quality furniture furniture baby furniture.