Feature/typeof#265
Conversation
|
@stackasaur is attempting to deploy a commit to the Beyond The Cloud Team on Vercel. A member of the Team first needs to authorize it. |
|
Haven't written unit tests yet. I added the neccesary classes to add the |
@stackasaur perfect! I'll review it as soon I'll have time! |
|
|
||
| // WHEN | ||
| Typeof when(SObjectType whenObject); | ||
|
|
There was a problem hiding this comment.
Could we remove that additional spaces? To have it similar to the other interfaces?
Interface itself looks great!
| private class SoqlTypeOf implements Typeof { | ||
| private String ofField; | ||
| private Map<SObjectType, SoqlFields> fieldsByType; | ||
| private SObjectType[] whenTypes; |
There was a problem hiding this comment.
Could we use List<SObjectType> to be consistent with the whole lib?
There was a problem hiding this comment.
I'd argue that the whole lib should use SObjectType[] as that syntax saves a decent number of characters.
But I'll change it to meet the others. Changes to lower character count would be an entirely different issue.
There was a problem hiding this comment.
hmm. It rather depends what you have to do.
Lists size is dynamic, Arrays size is fixed.
The whenTypes list should be dynamic in our case. We don't know the size as items can be added dynamically.
There was a problem hiding this comment.
In Apex, there is no functional difference between the two though as Account[] accts = new List<Account>() and List<Account> accts = new Account[0]
You can't also denote an empty list as Account[] accts = new Account[]{} which I'd say implies the dynamic sizing while still cutting down on characters
There was a problem hiding this comment.
I'll check performance, and if it's the same, what can I say: It's time to switch to [ ] 👯
|
|
||
| private class SoqlTypeOf implements Typeof { | ||
| private String ofField; | ||
| private Map<SObjectType, SoqlFields> fieldsByType; |
There was a problem hiding this comment.
We can set the value here:
private Map<SObjectType, SoqlFields> fieldsByType new Map<SObjectType, SoqlFields>();
private List<SObjectType> whenTypes = new List<SObjectType>();There was a problem hiding this comment.
This was an intentional decision to answer the question "what should happen if you call of again?"
I figured it should either throw an exception or it should clear out the existing when/then clauses, and I chose the latter since I couldn't find many examples of the framework throwing exceptions for things like this.
There was a problem hiding this comment.
Fair!
I would lean a little bit to an exception approach, as the syntax:
SOQL.Type.of(...).of(...)looks a bit strange and shouldn't be allowed. I'll add another github issue to take care of other places.
There was a problem hiding this comment.
Since there aren't any custom Exceptions in this class yet, how would you like to handle it?
I could probably argue that this is a use case for the built in IllegalArgumentException, but that may also feel a bit strange since it's essentially calling a setter twice which one would normally expect to work
There was a problem hiding this comment.
We use the built-in exception QueryException.
throw new QueryException('My message');We use it already in other places in the SOQL Lib.
| return this.of(ofField.getDescribe().getRelationshipName()); | ||
| } | ||
|
|
||
| private SoqlFields getSoqlFields(SObjectType whenObject){ |
There was a problem hiding this comment.
The getSoqlFields is private and it's invoked in methods below, could we move it at the end of the class?
There are two reasons:
- It's
privateand doesn't have to be seen. - Read flow - it's invoked later, but defined first. It would have sense to have the definition below invocation.
|
|
||
| private SoqlFields getSoqlFields(SObjectType whenObject){ | ||
| SoqlFields ret = this.fieldsByType.get(whenObject); | ||
| if (ret == null){ |
There was a problem hiding this comment.
Could we change the name from ret to something more descriptive?
| private SoqlFields getElseFields(){ | ||
| SoqlFields ret = this.elseFields; | ||
| if (ret == null){ | ||
| ret = new SoqlFields(null); |
There was a problem hiding this comment.
Lets overload the SoqlFields constuctor so we don't have to pass SoqlFields.
Just create
public SoqlFields() {
// default constructor
}|
|
||
| public SoqlTypeOf when(SObjectType whenObject) { | ||
| if (!fieldsByType.containsKey(whenObject)){ | ||
| this.fieldsByType.put(whenObject,null); |
There was a problem hiding this comment.
Why not like that?
this.fieldsByType.put(whenObject, new SoqlFields(whenObject.toString()));so you don't have to do if (ret == null){ + you won't need this.getSoqlFields
public Typeof then(SObjectField field) {
this.latestWhen().plainFields.add(field.toString());
return this;
}| String suffix = ' END'; | ||
|
|
||
| for (SObjectType t : this.whenTypes){ | ||
| SoqlFields fields = this.fieldsByType.get(t); |
There was a problem hiding this comment.
Maybe let's create a new inner class TypeOfWhenThenFields?
I would like to avoid fieldStr = fieldStr.substring(7); // remove the SELECT
Another reason is that SoqlFields has a lot of logic that we doesn't need.
We will duplicate the logic a bit, but it's not a bad duplication.
The whole WHEN - THEN build can be hidden inside TypeOfWhenThenFields, so this one (SoqlTypeOf) will be just a wrapper that will add 'TYPEOF ' + this.ofField + ' '; and ' END';
public class TypeOfWhenThenFields
public PlainFields plainFields = new PlainFields();
public RelationshipFields relationshipFields = new RelationshipFields();
}There was a problem hiding this comment.
I fully agree.
I was hesitant to create a new inner class for that as SoqlFields did meet the requirements with very little workaround needed, and I wanted to avoid adding what would be a significant number of characters.
Adding this will address several of your above comments.
pgajek2
left a comment
There was a problem hiding this comment.
I like it! Nice work!
If you disagree with anything, feel free to raise it.
|
What is the expected behavior of situations like this:
Throw Exceptions? |
|
I've addressed all of your comments |
I would say: Let SFDC throw it when executed - as it's default behaviour, let's keep it in this way. |
|
@stackasaur all looks good, you can continue with the unit tests. |
|
@pgajek2 , It doesn't seem that any relationship fields are valid in the |
|
Tests completed. Updating documentation now |
| Assert.areEqual(fromDate, binding.get('v5'), 'The binding variable should match the expected value.'); | ||
| } | ||
|
|
||
| @IsTest |
There was a problem hiding this comment.
Could you adjust the test to be similar to the existing one?
I mean:
- Add // Setup // Test // Verify comments to be consistent with the existing ones.
- If possible, use chaining without a variable.
- Use the clause in context of the whole SOQL Lib.
String query = SOQL.of(...)
.with(SOQL.Type.of(Event.WhatId)
.when(Account.sObjectType).then(Account.Id, Account.Name, Account.BillingCity, Account.BillingState, Account.BillingPostalCode)
.when(Opportunity.sObjectType).then('Account',Account.Id, Account.Name, Account.BillingCity, Account.BillingState, Account.BillingPostalCode)
.whenElse(new List<String>{'Name'});
.toString();There was a problem hiding this comment.
So do asserts in the context of the whole query rather than just test the individual typeof clause here?
|
|
||
| @IsTest | ||
| static void typeOfClassRelationshipFields(){ | ||
| { |
There was a problem hiding this comment.
Does it work? You have brackets in weird places ;>
There was a problem hiding this comment.
Test coverage all works.
I did the brackets to split the various overloads for the same method into different scopes. I could alternatively make separate methods.
I just normally do this when testing methods of slightly different signatures like this since apex lacks a better way to group together "sub tests"

Description
Type of Change
Changes Made
Queryableinterface was modifiedRelated Issues
Fixes #235
Closes #
Testing
npm test)npm run lint)npm run prettier:verify)Screenshots
Checklist
Additional Notes