Random Musings
A blog for whatever interests me at any given time.
Friday, April 13, 2012
What is Right vs. What is Best
Laws represent a framework by which a society provides a framework for its members to operate within. As such, the reason that laws should be made is not to do the "right" thing, but to do the "best" thing that provides such a framework. Often the best thing is the right thing, but sometimes it is not and I think that those times lead to the hardest decisions. As Americans we have been told to always do the "right" thing and to stand by justice and fairness, but this is not always the correct thing to do and I believe that this has the potential to hinder our society and nowhere is this more evident than in copyright law.
Protecting those who create by not allowing others to profit from their creation is the "right" thing to do. It screams to us that it is only fair, that justice demands that strong copyright law must be made and enforced. However, in this case I believe that we need to look at what is best. These strong copyrights seem to be holding back innovation and causing funds that could be use to further our society to be funneled into the black hole that is the legal system. This is clearly not what is best.
What really bothers me is that in the beginning the founding fathers of the USA got this. Many aspects of the Constitution take the side of what is best and not what is "right". Innocent until proven guilty, freedom of speech, the right to bear arms, due process; all these things are not the most "Right" solution, they can lead to criminals going free and people being hurt, but they are the "best" solutions for a free society. And these are just the things that I can think of off the top of my head, I am sure that there are many more examples if I actually looked.
This disconnect, between the founding father's "best" solutions, and modern day society's "right" solutions, is what is causing all the legal confusion. To make it worse we have corporate interests throwing around huge sums of money and preying on people's sense of "right" to spin laws and policies in their favor. It is, to put it bluntly, a mess and I am truly not sure what the answer is.
Thursday, March 15, 2012
A Case Against Copyright
It all stemmed from the basis of copyright. For reference, here is the legal basis for copyright law in the US:
The Congress shall have power: ... To promote the progress of science and useful arts, by securing for limited times to authors and inventors the exclusive right to their respective writings and discoveries;
So, considering this, I realizing that I was looking at a work of art. Moreover, this work of art was carved into stone hundreds of years ago, and likely was carved into that stone by another stone. The process must have been slow and excruciating, and all this at a time when simple survival was a daily fight. Picture, if you will, a hunter spending all day desperately searching for food to feed himself, his family, and his tribe. Then when he finally quits for the day, he spends his free time scratching a rock with another rock, all in the name of cultural expression, resulting in a wonderful piece of art that has survived hundreds of years, and barring disaster, can survive for hundreds more.
In the face of that, I realized that people will create art in the most adverse of conditions and that all that is really needed to promote the progress of the arts is to get out of the way and let people be people, not restrict them with over-bearing copyright laws.
Tuesday, March 6, 2012
Visualforce custom related list component
Some quick background, the company that I wrote this for has bastardized the Opportunity object and uses it as a Lead, Opportunity, and Quote object all rolled into one. Since they sell highly customized products, the opportunity object has several record types and many custom fields to allow all this functionality. What I was doing was adding some fields that are needed on every record type of opportunity. Since most of the standard page layouts for the record types were already fairly cluttered, it was decided that we would put these fields on a custom VF page that would be accessed from a button on the Opportunity.
So far so good, but then the project expanded and we needed to add another opportunity child object, however we wanted the related list to be on this custom VF page, but not on the main opportunity pages. I tried the
Looking at the situation, I decided that I could code my own related list, but I decided that I would attempt to make a custom component out of it, so that I could reuse it in any similar situations. I decided that the custom component would use dynamic apex to generate the VF tags making it generic as possible. In essence I wanted to be able to do this:
<c:customRelatedList object = "my_Child__c" fields = "ID,Name,my_Field_1__c" lookup = "myLookupField__c"></c:customRelatedList>
Here is where I ran into problems. Specifically I ran into problems with when the attributes are bound to variables in the controller of the custom component. Essentially, from what I gather, the members of the controller class are not set unit after the component is rendered. Basically it seems to me that the components controller is initialized, the VF tags in the component are rendered, then the attributes are bound to the member variables, finally all this is returned to the VF page.
This proved problematic because I could not access the fields attribute when the component called the dynamic VF method, and so I had no way to tell the VF how many fields were being displayed on the related list, or any way to set the column headers to the column name. My solution to this, is to use URL parameters and set the appropriate member variables in the constructor. Not the best situation, but the only one that was possible without hard coding the data in the controller class. Both ways would have their pluses and minuses, and I believe that the controller could be easily adapted to be hard coded instead of using URL parameters.
Anyway, I know that that was a little long winded, but here is the code that I ended up using, please comment if you have any suggestions or questions:
/*Class CustomRelatedList * Driver class responsible for creating and displaying customized related * lists on Visualforce pages * Data Members: * objectType - the object to query for the related list records * fields - A single string containing all the API field names separated * by commas. * relatedField - the name of the field that contains lookup information * to the main record displayed on the page. * thisID - A string containing the id of the main record on the page. * fieldList - a list of strings where each member contains the API name of * a field to display on the related list. * query - a string that contains the query that retrieves the records * for the related list. * objPrefix - a string that contains the three letter system prefix for * * data - a list of sObjects that contain the data returned by the query. * oppName - the name of the opportunity being acted on in this particular * implementation. Used to set a field on the child object when * the 'New' button is pressed * * * Methods: * CustomRelatedList() - constructor, sets up the memeber variables. * Component.Apex.Pageblock getOutput() - outputs the related list to * the calling custom component. * Component.Apex.OutputText getError() - a bebugging method to output * any necessary debugging data. * public string createQuery() - creats the SOQL query for the related records.3 * sObject[] getRecords () - returns the records for display. * string[] splitFields() - splits a comma seperated list of fields into an array. * public string getObjectCode() - returns the three character object code for the related * object. * public pageReference newQ() - returns a page reference to the new record page of the * related object. * public string fieldCleanUp (string s) - returns a readabe field name when given an * API field name by removing all underscores and the last '__c' * static testMethod void testCustomRelatedList() - test method for the class * * Created February 20, 2012 by Jacob Gmerek, change log to follow * */ Public Class CustomRelatedList{ public String objectType {get; set;} public String fields {get; set;} public String relatedField {get; set;} public String thisID {get; set;} public String[] fieldList = new string[]{}; public String query{get; set;} public String objPrefix {get; set;} public sObject[] data {get; set;} public string oppName {get; set;} public CustomRelatedList() { //get URL parameters thisID = System.currentPageReference().getParameters().get('id'); objectType = System.currentPageReference().getParameters().get('RelatedObj'); relatedField = System.currentPageReference().getParameters().get('RelatedField'); fields = System.currentPageReference().getParameters().get('Fields'); //Set up other data members query = this.createQuery(); fieldList = this.splitFields(); objPrefix = this.getObjectCode(); system.debug ('Query---->' + query); data = Database.query(query); List o = new List([select name from opportunity where ID =: thisID LIMIT 1]); if (o.size() > 0){ oppName = o[0].name; } } Public Component.Apex.Pageblock getOutput(){ //set up outer components Component.Apex.Pageblock myPageBlock = new Component.Apex.Pageblock(); myPageBlock.title = 'Opportunity Questions'; Component.Apex.PageblockTable myPageBlockTable = new Component.Apex.PageblockTable(); myPageBlockTable.expressions.value = '{!records}'; myPageBlockTable.var = 'Record'; Component.Apex.PageblockButtons myPageblockButtons = new Component.Apex.PageblockButtons(); myPageblockButtons.location = 'Top'; Component.Apex.CommandButton newButton = new Component.Apex.CommandButton(); newButton.expressions.action = '{!newQ}'; newButton.value = 'New'; myPageBlock.childComponents.add(myPageblockButtons); myPageBlock.childComponents.add(myPageBlockTable); myPageblockButtons.childComponents.add(newButton); //Loop through the field list to set up the columns for (integer i = 0; i < fieldList.size(); i++){ Component.Apex.Column col = new Component.Apex.Column(); Component.Apex.outputField out = new Component.Apex.outputField(); out.Expressions.value = '{!Record.' + fieldList[i] + '}'; col.headerValue = fieldCleanUp(fieldList[i]); //Set the name field as a hyperlink if (fieldList[i] == 'Name'){ Component.Apex.outputLink Link = new Component.Apex.outputLink(); Link.expressions.Value = '/{!Record.ID}'; myPageBlockTable.childComponents.add(col); Link.childComponents.add(out); col.childComponents.add(Link); }//end if else{ myPageBlockTable.childComponents.add(col); col.childComponents.add(out); }//end else }//end for return myPageBlock; } Public Component.Apex.OutputText getError(){ Component.Apex.outputText err = new Component.Apex.outputText(); err.value = ''; //use for debugging return err; } public string createQuery(){ return 'Select ' + fields + ' from ' + objectType + ' WHERE ' + relatedField + ' = \'' + thisID + '\''; } public sObject[] getRecords (){ return data; } public string[] splitFields(){ return fields.split(',', 0); } public string getObjectCode(){ Map objs = schema.getGlobalDescribe(); return objs.get(objectType).getDescribe().getKeyPrefix(); } public pageReference newQ(){ // there are some hard coded parameters to fill out the lookup/detail field // when creating a new child. return new pagereference('/'+ objPrefix + '/e?retURL=' + thisID + '&CF00NR0000000tCFQ_lkid=' + thisID + '&CF00NR0000000tCFQ=' + oppName); } public string fieldCleanUp (string s){ s = s.replace('__c', ''); s = s.replace('_', ' '); return s; } static testMethod void testCustomRelatedList(){ account a = new account(Name ='test',BillingState='OH'); insert a; contact c = new contact (accountID = a.id, mailingState = 'OH', lastName = 'test'); insert c; pageReference pageRef = new pageReference('/apex/myPage?id=' + a.id + '&RelatedObj=Contact&fields=id,name&RelatedField=AccountId'); test.setCurrentPageReference(pageRef); CustomRelatedList rel = new CustomRelatedList(); rel.getOutput(); rel.getError(); contact[] cList = rel.getRecords(); system.assertEquals(cList[0].id, c.id); pageReference p = rel.newQ(); system.assertEquals(p, new pageReference('/'+ rel.objPrefix + '/e?retURL=' + rel.thisID + '&CF00NR0000000tCFQ_lkid=' + rel.thisID + '&CF00NR0000000tCFQ=' + rel.oppName)); } }
And here is the actual component, it is pretty straight forward, but I thought that I would provide it anyway:
<apex:component controller="CustomRelatedList"> <apex:dynamicComponent componentValue="{!output}"/> <apex:dynamicComponent componentValue="{!error}"/> </apex:component>
Finally, here is an example URL from my org that calls the appropriate VF page and supplies the parameters to show the related list.
https://na3.salesforce.com/apex/SalesTracking?id={!Opportunity.Id}&RelatedObj=Opportunity_Questions__c&Fields=Name,Question__c, Answer__c,Asking_Department__c,Completed_Date__c&RelatedField=Opportunity__c
Monday, November 21, 2011
Salesforce and Max Trigger Depth
What Happens
Simply put when you are writing a trigger and start to insert items you get an error similar to this:
Why this Happens
Generally, when you receive this error you have updated the same object that your Trigger is working on with a DML statement in your trigger. Here is an example:
Trigger someTrigger on some_obj__c (before insert, before update){
for (some_Obj__c o: trigger.new){
o.somefield__c = 'This is my data';
update o;
}
}
Now there are several things wrong with that trigger, but for our purposes the one that matters is the I am updating some_Obj__c in a trigger on that same object that activates on update. So what happens is that the trigger is called, the object is updated, the trigger is called again and the object is updated again causing the trigger to be called again and so on. After a certain point there are too many triggers being called and you receive the error message above. Be warned that sometimes finding that DML statement, may not be as easy as it sounds. It could be in some utility class that is being called by a helper class that is called by your trigger and you may not even realize it!
How to solve the problem
Solving this problem my not be as easy as finding this problem. Obviously, the easiest way to resolve this issue would be to remove the offending DML statement, but this may not be possible so we have to investigate other workarounds.
1. Check a field on the object. Basically, create a scenario where the object has a field that will somehow indicate that the record has already been updated. Then all you do is check this field, if it indicates that the record has already been updated, then you do not call the DML statement, the chain is broken and everything will terminate normally.
2. Use a static variable. This is similar to number one, but instead of using a field on the object, you use a static data member of a public class to check and see if the DML statement needs to be called. This is effective if there is no field on the object to indicate if the update needs to be performed, or if the update is on a different record than the one that fired the trigger.
There are probably other ways to stop the execution loop, but the general idea remains the same.
Wednesday, November 9, 2011
The Secret Life of Crows
Found an interesting article the other day (see above). It details the intelligence level of crows, which is remarkably high. As pointed out in the article, crows are capable of doing many things that the average human has trouble with, such as communication, memory and advanced planning. Although the article in itself is interesting it led me to examine a couple of things.
My first thought on reading this is, why are we just finding out about this now? I mean, crows have been around for thousands if not millions of years, probably have exhibited this behavior for a significant portion of that time, so why are we just now studying it? Here are the possible reasons that I came up with:
Reason #1: Just noticed
One reason that this could just now be coming to light is that the behavior in the crows was just observed recently, but I do not buy that one. For centuries, crows have been painted as evil. In order to be evil there has to be some sort of intelligence, albeit a malignant one. In many stories, crows are even able to talk, even when other animals can’t. This says that on some, possibly subconscious level humans have always realized that crows were smart and just have never really studied it. But why?
Reason #2: My take
The conclusion that I came to is that humans failed to recognize the intelligence of the crow because of a me-centric attitude. Humans always want to believe that we are special, that the world revolves around us, that something in the universe, be it our intelligence or even a higher being, provides us with a superiority over other animals. With this in mind, it is easy to see why we studied intelligence in chimps, apes, and other primates with way more voracity than other animals. These animals are the closest in their relation to us, thus, even if they are not as smart as us, they must be smarter than other animals. So we will study them before all else.
What's up with Force.com Test Code
On the force.com discussion boards for Apex coding and general development questions, one of the most often asked questions is how to write a test method for a given apex class. Some users have specific questions and some have no idea where to start writing test code, but I feel that most of these users have one thing in common: they do not understand the purpose of test code. I have seen many blog posts and comments on how to write test code and what structure to use, but very few of these touch upon the why of test coding or explain exactly what you are doing when writing test code.
Why do we write test code?
For the force.com platform test code serves as a check on bad programming. However, the way that it is utilized by force.com is misleading for many. When Force.com checks the coverage of a code, all that is checked is whether or not the code will run. One hundred percent code coverage is great, but really by itself is worthless as a test. As a simple example take the line:
Integer x = 1 + 2;
This is a perfectly valid line of code. If I call the method containing this line of code in my test class, this line will be covered and pose no problems. However, what if I need x to equal four? That 100% test coverage then gave me a false sense of security in code that is logically flawed. So a good test class needs to cover two scenarios, first it needs to ensure that all the code it is testing will run, i.e. the test must provide adequate code coverage. But also just as important, the test should ensure that the code will produce the result that it was meant to produce, i.e. that the code is logically sound.
How do we write test code?
When we go to write the test code then, how do we do it? I think that everyone may have a different method for this, but what I do is picture how the user will use the program that I am writing and write code to accomplish the same thing.
For example, say I write a VF page with a custom controller that takes the data entered on the page and inserts in into two different related custom objects, the first step would then be to programmatically enter data into the system, then I would insert the data into the appropriate objects. These two basic steps would provide me with 100% code coverage for that basic scenario, but my test is not finished. At this point I know that the code ran, but did it really insert the records, and just as importantly did the right data get into the right field? So to finish my testing scenario, I would query the records that I just inserted into the database and then compare the data that I queried with the data that I wanted to place in the database and ensure that they are the same. This would check the logic of my code and ensure that not only is the code running, but that it is running properly.
Is that it?
No, far from it. The controller method probably contains validation and condition checks to ensure that only the correct data is inserted and only inserted in the proper conditions. All of these validations and conditions must be checked as well in order to obtain 100% coverage and to ensure that our code is functioning as intended. We can check this by attempting to insert invalid data and/or conditions into the database. This will allow us to follow the various branches of the code and will give us the complete coverage that we want.
So are we done yet?
Yes, for now. The points that we have covered here should allow you to approach writing test code with a clear and concise plan of attack, allowing you to avoid the frustration of 74% code coverage or 100% code coverage for code that does not work.