Showing posts with label coding. Show all posts
Showing posts with label coding. Show all posts

Saturday, January 19, 2019

Easy SFDX for Enterprise and Others

When cousin Tim Toady took the doorknob and lock apart on the back door after his key broke, he had a lot of trouble figuring out how to put it back together.  With a hundred tiny pieces laid out across the kitchen, Auntie Pat Tern sifted out a dozen of the most important, handed it to cousin Tim and told him to just use that for now.  Unsatisfied, Tim tried to put a few more parts back in, triggered the spring and the entire thing exploded across the kitchen again.That's when Auntie Pat Tern reminded him of two guiding principles: 1) Keep It So Simple and 2) Keep track of all your changes.  He could have taped each piece to a sheet of paper, in order, as he dismantled the lock, for example.

That reminded me of the guiding principles behind implementing Salesforce Developer Experience for the Enterprise Org.  Staying Agile means finding the Minimum Viable Product for tools you implement, not just products you build, so here is my guide to easy SFDX for the Enterprise. (See part 2 of this post for the actual commands.)

SFDX MVP


1. Discover:  A little reading reveals that SFDX is intended to "enable source-driven development, team collaboration with governance, and new levels of agility".  To accomplish this, it offers the important benefit of using "developer tools you already know." Use what you know, that's easy.

One thing we know in our Enterprise orgs is that configuration changes may happen in Production to meet immediate release requirements.  So the Production org itself is always the absolute source of truth for the org.  You can't just implement source control and claim that the source of truth is there because the bugs your users report will be found in Production and hopefully easily reproduced in Sandbox, that easily created org copy that is a developer tool you already know.

So the first step is to use the developer tools you already know: Production is source of truth for code and metadata and Sandboxes provide great individual and team test environments.  Keep them all. Use Dev Hub in Production to enable command line logins to these orgs.

2. Develop: SFDX includes a Command Line Interface (CLI) that lets you connect to your Enterprise Production org as well as your Sandboxes using simple and batchable commands. That gives you the power to make use of local tools, including local code editing and version control by connecting the CLI to your orgs and pulling down the code to edit locally.

Different Developer Sandboxes and different bits of code on the local computer make keeping track of all the versions and making sure they are merged and integrated into the larger system for testing means that version control is more important than ever.

For version control, we use Git on the local computer and cloud-based systems like GitHub for team backups and version control. Our local git directory can be connected to our own personal branch (or maybe to a feature branch) of the org repository in GitHub. Following tech review, developer branches can be merged into the main code branch. And this can be automated so that a developer's work gets backed up from their local computers to the cloud repo on a regular basis.

You already know about backups and version control if you use something like Microsoft Word.  It periodically auto-saves the working version of your documents. If your computer crashes, you have a choice between loading a version you saved or a version that Word automatically saved.  Version control to the rescue!  That can definitely be useful when you are doing Test Driven Development and your test fails because of your last set of changes and you decide to roll those back to the previous successful version.

If you use Git for version control of your work on your computer, you can keep track of versions.  And you can post those versions to GitHub, BitBucket or similar.  These tools can make team collaboration easier with everyone checking their latest working version into the repository in the cloud. It's like the difference between Word on your local computer and Quip Documents in the cloud.  Collaboration can be simplified with cloud solutions. And you can create a process for branches that get merged into a single main repository based on your own team's organization.

We have different repositories for different platforms we develop on.  And developers are free to create their own repositories for their own organization as well.  One developer keeps every feature in separate branches and another developer keeps just a local repo and a cloud repo, no branches. For our org-wide repository, we have branches based on releases so that short-term and long-term projects are kept separate.

The CLI adds flexibility to our Development Cycle by letting individuals choose tools they are familiar with and develop code locally or continue to develop in the Dev Console even, either way we can create a single shared backup and version control repository of everyone's work thanks to simple CLI commands.

3. Retrieve and Deploy: Following our SFDX process of using what you already know, we can easily coordinate the efforts of admins who make configuration changes in Sandbox into our version control as well as developers who want to edit code with apps they run on their own computer.  Salesforce provides two easy tools to work with the CLI: Packages and Outbound Change Sets.  If you haven't tried both, take a look in Setup>Home for them.

Packages give you the chance to define related sets of custom code and custom configuration metadata. Choose a bit of code and dependency data like custom objects and fields are automatically added. You can create Packages to look for overlap of functional dependencies in your org. And to help you document feature specifications.

Outbound Change Sets give you a bit more control to stick to only code and configuration that has immediately changed, and not include more stable code and configuration from prior development that is already in Production. You can use these to get the most up-to-date configuration changes on the fly from production for anything you need to work on.

Both Packages and Outbound Change Sets can be pulled out of the org and onto the local computer using the CLI retrieve command. These can also be deployed to any other org (yes, including Production) using the CLI deploy command.  Retrieve pulls down a Zip file including a package.xml defining what has been retrieved and folders of metadata, all the same for packages or change sets. You can unzip this into your local Git directory to update your version and you can use the CLI to deploy back to any org after you've made changes. In between, backup ongoing work to shared repositories to merge changes for the next stage of the development cycle.

Sticking with these familiar tools, we not only keep it simple, but we ensure that Admins and Devs can work well together because the org remains the source of truth and work efforts can be tracked, changes can be audited all in the org as usual.

4. Iterate: Since we have the ability to connect to our familiar Enterprise orgs as well as the ability to work on changes locally and use tools for searching and comparing code and configuration versions, we create a stronger collaboration.  Since we can use Git commands on our local computer to manage the backup and version control, we have even better insights along the development cycle, regardless of Sandbox refreshes.

With changes happening in a variety of orgs, local repositories may need to rebase if a branch gets too far our of sync. For Enterprise orgs, the source of truth is what your users see when they report bugs and praise new features. So bringing your local repository back into sync with upstream changes is simplified.

If you have separate repositories for each development stage from Integration to UAT, Staging, and Production, developers can retrieve changes at each point in the process. This makes it even easier to compare versions when a feature breaks after an upstream deployment.  Verifying whether the correct version was deployed with all of its component parts can be done locally, in shared repositories, and by auditing recent deployments right in the orgs.  And reverting to another version of a feature is even easier when you have backups in version control at each step.

Benefits of Change


SFDX helps Enterprise orgs follow Auntie Pat Tern's advice: Keep It So Simple and keep track of all your changes.  By allowing admins and devs both to work with tools most familiar to them, at the same time, SFDX offers greater insight and transparency into the development cycle. Because the CLI opens up opportunities to make use of tools like VS Code and online repositories, debugging throughout the release processes may be simplified as well.  And the CLI gives the power to make everything more automated for a more continuous integration of changes into each new environment at every stage of Enterprise development.

Ultimately, the best implementation of the Salesforce Developer Experience is to make use of what you know and implement it your way, just like the SFDX Developer Guide recommends. Give yourself even more power with command line deployment and retrieval of packages pre-defined in your orgs through easy and familiar Salesforce Setup options. Get even more peace of mind with backups at each stage of the release process thanks to the CLI and Git local repositories connected to shared repositories online.

Sunday, April 10, 2016

Putting Governor Limits To The Test

My Auntie Pat Tern is pretty accepting of cousin Tim Toady's behavior. "He's a teenager, after all, there's no better time for him to test his limits," she explained. So I decided to ask my developers to test their limits in Salesforce.

One Master object with 13 Detail objects, 
some of which are Masters in other relationships as well.
I wanted them to see for themselves how governor limits benefit the overall performance of the code they write. And I wanted them to experiment with ways to push those limits by trying to break things.

They built Processes, wrote triggers, and configured some unwieldy objects that I would never want to see in production all in an effort to push good performance to the very edge of being bad.

Some limits include object relationships.
A couple of these experiments proved that what they understood about limits was untrue. In one example, when it comes to Master-Detail relationships on custom objects, the documentation described a limit of 2^3. Firstly, 2^3 does not equal 8 here. Instead, it indicates that an object can have two M-D relationships and those can be three levels deep.

Take the example Parent <-- Child <-- GrandChild <-- GreatGrandChild where all relationships are Master <-- Detail. Some of the limits on this relationship structure are as follows:

  • Parent cannot have a new Master (eg GrandParent) because of the limit on how deep the relationship levels can be. 
  • GreatGrandChild does not show up as available to be a Master in other relationships because we are limited to three levels deep.
  • Child cannot have a new Master because it already has two M <-- D relationships (even though only one of those points to a Master).
  • Child can have new Details, that is, new GrandChild-level objects can be created as Details for Child even though Child already has two M <-- D relationships.
  • Many Child-level objects can be created as Details for Parent (we stopped at over 50). 
  • A Child-level object cannot be used as a junction object between records of a single Parent-level object. M <-- D relationships cannot be immediately self referencing like that.
  • GrandChild-level and GreatGrandChild-level objects can have the same Master object as their Master, eg. GrandChild can point to Child and Parent as Masters even when Child already points to Parent as its Master. We daisy-chained six objects this way before hitting limits on the depth of the relationships.
  • Child-level objects with two relationships pointing to Master objects cannot be Masters to new GrandChild-level objects. An object can have two Masters or it can have one Master and many Detail relationships or it can have no Master and many Detail relationships.

It was a fun exercise and demonstrated how limits benefit performance and how hard some of them can be to break. It gave the developers a chance to challenge their assumptions, be creative and gain a better understanding of the implications of limits when it comes to writing better code.

Secretly, Auntie Pattern believes that testing limits can help us appreciate why limits are important, but she wouldn't tell Tim Toady that.

Sunday, April 3, 2016

Painless Removal Of Boat Anchors

I asked my Auntie Pat Tern why she has a tattoo of a boat anchor on her forearm and she said, "Boat anchors symbolize hope, but I'm considering getting this one removed." So she didn't have it to enhance her resemblance to Popeye like cousin Tim Toady always says.

It may have been hope that also inspired the boat anchor I found in the code in my org. In technical circles, some people only think of boat anchors as that outside technology they got stuck with because their boss bought it without conducting a technical review. But if you aren't constantly conducting a technical review of your own code, you can get stuck with boat anchors there as well.

In my org, I found something like the following:

All code that had once handled business logic was commented out to the point where the code literally did nothing but returned a null value. I think this boat anchor represented the developer's hope that the original code might somehow be useful later. If that's the hope, the code can be stored outside of our production org.

To remove it, we just needed to correct any references and delete the class and its related unit test. Salesforce offers multiple ways to accomplish this using the IDE, the developer Workbench or the Migration Tool, all of which are much less painful than Auntie Pat Tern's tattoo removal.

With Workbench, for example, you can simply mark a class or trigger as deleted or as inactive to remove it from production using the following steps after downloading the class or trigger files:
  1. Edit the XML meta file for the class or trigger to change its status from <status>Active</status> to <status>Deleted</status> (for classes) or <status>Inactive</status> (for triggers)
  2. Put the both the .XML file and class or trigger file into a folder named "classes".
  3. Create a package.xml file to list the class or trigger to be deleted or made inactive.
  4. Place both the package.xml file and the classes folder into another folder inside a zip file.
  5. Specify this zip file after you select Migration>Deploy in Workbench.
A great way to generate a package.xml file to get you started is to use Setup>Create>Packages in Salesforce and add the classes or triggers that need to be deactivated or deleted. This package can then be specified for download in Workbench using Migration>Retrieve. The zip file will need to be changed as described above to deploy. (For step-by-step instructions, click here.)

Like Auntie Pat Tern, be on the lookout for boat anchors and consider removing them when they pop up during your org's ongoing technical review.

Friday, March 11, 2016

Static V. Instance, or, How Can A Variable Be Unchanging?

I asked my Auntie Pat Tern why she loves to watch Jeopardy! and she said, "if I watch it enough, I will see answers to all the questions in the world." So I looked through the questions that my developers ask to see if they could be answered by Jeopardy!

One of the questions that comes up frequently is whether use of the 'static' keyword is an antipattern or whether it is best practice. Of course, if it's used wrong, it is an antipattern, so understanding static versus instance methods, variables and initialization code is important.
Final Jeopardy! means there won't be
infinite answers this time.

Taking Jeopardy! as our example, the classic game show that contestants win by providing the most correct responses, we can see that some things don't change from week to week. The show's name, the show's host, these are constants and so of course are static because "static" means unchanging. A static response can be provided for questions about the host and show name.

Every show has three contestants and to create a show, its producers need to know who the three contestants will be. So they conduct tryouts to choose and schedule competitors. The names of the competitors change from night to night, so the list of competitors is variable, but show producers have to know who is scheduled before the show is created, so it is a static variable. A static response can be provided to the question of who will be the competitors for any specified date.

When the show is filmed, the responses that one contestant provides as part of the action of the show are defined by the instance of the show and depend on the inputs the contestant receives from the show and the interactions the contestant has with other contestants on that particular show. So these responses are non-static and depend on the instance of the show.

As an example let's consider three possible questions about the upcoming Jeopardy! college championship round:
  1. Who's the host? We expect one answer: 'Alex Trebek'. 
  2. Who are the competitors? We expect one answer: the three college students, depending on who is chosen for a specified day. 
  3. What is the contestant's 'question' and score for the first input in the first category? The response to this question depends on actually seeing the college championship round in action, knowing what the inputs are and seeing which contestant acts first and the result of that particular action.  
So the first two are static and the last one non-static and specific to its instance.  

In Apex, you can see an example of static vs. instance in the Date class. This class offers both static and instance methods. Let's consider three possible questions we could ask today:
  1. What is the date today? We expect one specific answer for this question and it doesn't need any additional information for us to ask it: Date.today().
  2. Is it a leap year? We expect only one answer for this question, depending on a specified year, for example: Date.isLeapYear(2016); or Date.isLeapYear(2023);.
  3. What is the year? The response depends on knowing the date in question -- we need an instance of Date in order to figure out the year of that specific date, for example: Date yearLater = Date.today().addYears(1); Integer nextYear = yearLater.year();.
Again, the first two are static methods while the third, determining the year, is specific to its instance. You might wonder, for example, what happens in Apex when you add a year to a leap day, will Apex give us February 28 or March 1 of the next year (or null)? You could run the following code to create an instance specific to a leap day and test it out:

The above code primarily uses instance methods, but using the 'static' keyword in Apex can be particularly useful when it comes to writing code called by Triggers. Since a single Trigger can result in a cascade of other Triggers firing, we may need to keep track of some information across all the business process automation associated with the cascade of Triggers. Having a separate class with a static method or variable for all of the Triggers allows us to share specific data across the code executing for multiple Triggers.

For example, a separate class that contains a static variable can indicate the number of times a particular automation has run to help avoid an infinite recursion. 

Infinite recursions need to be avoided in code, but Auntie Pat Tern may be correct that infinite episodes of Jeopardy! will contain all the answers to all the questions in the world.



Friday, March 4, 2016

Start Documenting Rather Than Accepting "No Comment"

My Auntie Pat Tern tried to convince my cousin Tim Toady that he should be using the 3/5 rule of essay writing he'd been taught -- three ideas, five paragraphs -- but, as usual, Tim insisted there is more than one way to do it (TIMTOWTDI). So I looked through the code in my Salesforce org to see if my developers were following the 3/5 rule for comments or if TIMTOWTDI had gotten into our code.  Unfortunately, I mostly found code with no comments at all.

Code without comments is like a research paper without a thesis statement to detail its purpose.  It's like doing something over and over without understanding why because comments should always clarify why it does what it does.  It's like burying treasure without leaving a proper map because good comments point to valuable resources the code uses or makes available.

Code comments should follow the 3/5 rule of comments:  there are three places where comments should occur and five specific topics that need to be addressed.

The three places where comments should be found in Apex code are:
  1. Block comments at the beginning of classes.
  2. Block comments at the beginning of methods.
  3. Line level comments for constants, loops, conditions, and where clarification is possible.
The five topics that should always be found in block comments are:
  1. Description of purpose and assumptions.
  2. Author/date for creation and modification.
  3. Parameters for methods that accept values, or none.
  4. Return values for methods that pass values, or none.
  5. References and dependencies.
Here's an example of code that follows the 3/5 rule of comments:



In this example, block comments appear at the start of the class and at the start of the methods while inline comments appear within methods and for named constants. The comments use Javadoc tags like "@description" to make the important topics easy to locate.  These comments even include "TBD" to indicate code that is incomplete and point out the limitation imposed by the choice of Integer as a data type rather than Long. Comments should always include information that may be reconsidered during the next phase of development.

We ask that developers and admins both be responsible for code comments because the admin should know how code effects data integrity and user experience.  Without that level of cooperation and understanding, admins have been known to implement validation rules that cause code to fail and developers have been known to implement code that causes user experience to decline.

Tim Toady is right, there is more than one way to do it with code.  That's why we ask for comments that explain why the code was written the way it was.  And we follow Auntie Pat Tern's 3/5 rule to make sure we have comments in three areas of code and covering 5 required topics.  Better comments lead to better collaboration and easier maintenance of the code and the org where it runs.

Wednesday, February 24, 2016

Using Trailhead To Resolve Unknown Unknowns

According to my Auntie Pat Tern, the only trouble with my cousin Tim Toady is that "like every teenager, he don't know what he don't know.  And that wouldn't be so bad if his teachers were better at knowing what he don't know."  So I took a look at the code in my org to see if I could pinpoint what it is that the developers don't know.

Luckily, the Trailhead team is great at foreseeing what it is that people don't know about Salesforce and have created a Trail for that, no matter what that is.  And while the developers might find the Apex trails on their own, they might not recognize that there is more about Salesforce they need to understand.  In fact, there is an entire Trail on the Salesforce Advantage, the core technology that differentiates Salesforce from other CRM systems and other development platforms.

Learn, or review, Salesforce Technology Basics
with the new Trailhead module.
One developer expressed concerns about "the Governor's limits", which indicates to me that they need to better understand multitenancy and performance.  Another expressed concern about Salesforce firewalls and security breaches, which indicates they need to learn about Salesforce security standards.  A third developer suggested we build custom objects for storing employee contact data and build content management and customer service solutions from scratch, which meant they need to learn more about fast app development with Salesforce customizations and third-party apps.

Happily, Salesforce has a new Trailhead module to help my group know more about all these topics, Salesforce Technology Basics.  Of course my developers are a lot like my cousin Tim Toady, they know they are a smart bunch but they often don't realize that there are things they don't know.  It's the Dunning-Kruger Effect, the unknown unknowns.

For those who are deeply familiar with Salesforce, Trailhead can help you avoid the "curse of knowledge" tendency to believe that if you know it then most people must know it as well.  Trailhead modules are thorough, starting with the basics and moving to more challenging information.  And they are entertaining, so anyone with a smattering of knowledge will find familiar topics fun to review and new topics informative.

With Trailhead, you can avoid the problem Auntie Pat Tern described for cousin Tim Toady, the unknown unknowns as well as the curse of knowledge.  Just encourage your team to earn Trailhead badges, which you can review in their Salesforce Community Profile pages, to bring the team up to speed even when you, or they, think they know what they need to know already.

Sunday, February 21, 2016

Code Smell Leads To Improved Interprocess Communications

My Auntie Pat Tern said she always knows when her teenage kids have guests over and her friend wondered how.  Is it the noise, the mess, the smell? "No," said Auntie Pat Tern, "I just ask them and they tell me."  So I thought I would look through the code in my org and pass this straight-forward idea for communication on to my developers.

When code review uncovers a lot of small problems, this can often bring larger problems to the surface. "Code Smell" refers to small problems that may reveal bigger concerns in code. I previously gave an example of code that uses a 'poltergeist' object to pass data from an external system into a custom Salesforce object before creating the data in the required Salesforce object.  The same code also uses 'hard coded' values that are not named constants.  And that "Code Smell" reveals the use of a database field for interprocess communications, setting a field value to 'success' when the record is created rather than relying on more direct means of communication.


Using the Apex Database class, as shown in the second code block, provides a direct means of communication that would make Auntie Pat Tern proud.

Sunday, February 14, 2016

Poltergeist Busters Get A Call

Auntie Pat Tern mentioned that she loves a good ghost story, so I looked through my code and told her about the Poltergeist object I found there.

Poltergeist objects exist simply for the purpose of passing data from one place to another and are essentially useless.  These objects don't serve a clear function relative to business or technology rules, instead they just take up space.  Poltergeists are unlike Leads, which are required by business rules to hold data until it can be verified and converted to Contacts.  Leads aren't Poltergeists because they service the business rules related to data verification.

The object I found in my code was no Lead, it was a troublesome Poltergeist.
In the above code, the Order object serves no purpose other than passing data from an external system into Salesforce.  Since there is no verification process defined, there doesn't need to be a holding bin for data, and it could be passed directly into the Sales Order object that already existed in our Salesforce org. We can simply refactor the code to write directly to the third-party object rather than the Poltergeist.

Auntie Pat Tern said she's seen a lot of weird stuff, but the code in my org might be the scariest of all.

Thursday, February 11, 2016

When To Soft Code Or Not To Soft Code

My Auntie Pat Tern got mad at my no good cousin when he told her he changes phone numbers every time he gets a new burner phone; she warned us to make sure we do business by the rules.  So I looked through my code and shared her suggestion with my developers.

It turns out they tried to correct a problem with badly implemented hard-coded values by soft-coding some values that represented software architecture decisions and similar business rules.

Previously, I showed you the example of a hard-coded username being assigned as record owner, which caused two problems in the org.  The first problem was that the username needed to be an API-only user rather than an employee who might leave the company whose username would be deactivated.  The second problem was that the username was hard-coded deep in the code rather than being represented as a constant at the beginning of the class.

The developer who tried to fix these problems decided to soft-code the username as follows:

Using Custom Settings allows the username to be changed outside of code at any time, multiple times.  The above example does not solve the first problem we had, though. Unfortunately, soft-coding the username defeats our business rule requiring data coming from integrations to be owned by a user or Queue specific to that integration.  In other words, our business rule required the use of a constant rather than a soft-coded value.

We had to take that code back to the drawing board one more time because, like Auntie Pat Tern demonstrates, code should behave according to the rules of business, and enforce those rules automatically.


Monday, February 1, 2016

Avoiding the Negative for Clear Code

My Auntie Pat Tern recently reminded me to avoid double negatives and use positive language as often as possible. So I looked through some of the code in my org and decided to share her advice with my developers. When we write conditional statements using NOT (or "!"), we are using negative syntax which is more difficult to understand than positive syntax. Here's an example written in negative syntax, then rewritten in positive syntax:

The conditions evaluate the same, but I find the negative syntax more difficult to read during code review and maintenance. Note that it can be improved upon further with a basic knowledge of String methods.

The first time I encountered super negative syntax, I thought the developers who used it were making a game of being abstruse.  But knowing that the two programmers were friends led me to discover that this was in fact a case of "cargo cult programming" where they were sharing and reusing a bad pattern because they hadn't taken the time to pick apart what the code needed to accomplish. Once they better understood what the code was doing, they learned to write it more clearly.

Friday, December 5, 2014

Get Ready Glossary for Administrators Learning to Code

If you are and administrator learning to code, you already know more than you may realize.  I've started preparing a glossary to help you with programming terms by giving you similar examples from your daily tasks as a Salesforce Administrator.

Database customization and coding, it's all connected.
  • Data Types:  When you create custom fields, you have to specify a data type: Date, Text, Currency, Number, etc.
  • Polymorphism:  When you use "+" in a formula for two text fields, it concatenates, when you use it in a formula with two number fields it adds them.  This different behavior in different scenarios is polymorphism at work.
  • Variables:  Fields that let users input values are variables.  They can be changed if needed, just look for the label you gave and edit the data.
  • Constants:  Your org ID is a great example of a constant.  It's a value that will not change in your org.
  • Objects:  Okay, this is confusing.  When you start programming, you will see that Salesforce objects are now referred to as SObjects.  This is because object oriented programming languages use the term Objects to represent data collections.  Oh, hey, that's what objects are in Salesforce too, basically.  Only oop objects can also have actions related to them, things that you can do to them or things that they can do to other objects.  Oh, hey, sObjects are the same if you think about workflows as actions that are related to specific objects and think of triggers as actions that let one sObject act on another sObject.  So maybe this isn't confusing at all.
  • Array:  In the Salesforce database, you have a record ID associated with a bunch of fields -- record name, created date, etc.  This is essentially an array of data. Apex uses the term List rather than Array, but they are the same.  Lists can be multidimensional too.  For example, you can have a list of data from fields for a single contact record, or you can have multiple records in a list and each of those records will have its own list of field values.  List Views are two dimensional lists of data.
  • Cast:  In programming, you can force a variable of a particular data type to be treated like a different data type.  Similarly, in Salesforce, you can use Formulas like Text(PicklistSelection__c) to force a field, in this case a pick list, to be treated like a different type of data, in this case Text.
  • Model-View-Controller:  This is easy for you.  Model is the data model.  When you create custom objects and fields in Salesforce, you are changing the data model, native objects and fields are also part of the data model.  View is the user interface.  When you edit page layouts, you are changing the view.  Controller is any automation.  You might add workflow rules or formulas to affect data based on rules and reasons you define.
  • Boolean data: Think of a checkboxes.  They are true or false, checked or unchecked.
  • Boolean Operators: And, Or.   You may be using these in formulas or in list view filters already.  If you look for this value AND that value, both must be true.  If you look for this value OR that value, only one of them needs to be true, but both true will work as well.
  • SOQL: SObject Query Language lets you express in a few words the kinds of information you already use defining List Views.  For a List View, you sepcify filter criteria for selecting specified fields from the given object.  You might select First and Last Name from Contact with filters looking for records where the phone number is blank, for example.  SOQL lets you express the same sort of thing when programming in Apex, using a few key words.

If you want to write code for Salesforce, Visualforce will handle the View portion, Apex will handle the Controller portion, and Salesforce will continue to handle the Model portion of your program.  You will probably find yourself using data types you are very familiar with from Salesforce fields as you set up variables and constants.  And you will find SOQL easier to understand if you think of them in the context of list views, returning lists or arrays of data you request.

For a more complete introduction to programming for the administrator, please watch this Dreamforce session on coding for non-developers: http://dreamforce.vidyard.com/watch/haqgdyryAtDoQdMsOieTTA