logo

NJP

Salary Survey Analysis Tool: Part 2

Import · Oct 17, 2020 · video

[Music] so we are picking up where we left off last time i am building the salary survey analysis tool that's going to help me process the data from the uh seller salary survey that i put out here a short while ago um now i was doing some thinking on this one i haven't actually done any more work on it since the last one so there's nothing to really catch up on but i did do some thinking on it uh and i realized that my application state probably has some stuff that doesn't need to be there i can probably make it uh calculated data um using like a selector function or something like that so i wanted to spend just a moment here rethinking the application state so let's first take a look at what it is right now okay so there we go inspect element and reload uh get rid of the preserve log hide that oh i'm on the wrong salary survey analysis tool there we go there's my event log okay so we've got our event log kicking at this point let's see so right now the state contains our variances and it contains our responses now if i go to the variance split which is where we're getting the uh the that variances object the the property split variance variances from i am applying a filter to my data in this function and what i realized here was that this is probably not the only thing because i'm also planning on doing a histogram uh the histogram's probably going to have to use the same filter so why why apply the filter over and over and over again in different sections of the state it was starting to not make sense to me and you know when you look through redux documentation and stuff like that you'll see a lot of folks of talking about using the bare minimum application state and not having a bunch of state that you have to compute and you know basically compute what you need when you need it memoize it if you have to but when it comes to your application state keep it minimal uh so i wanted to do a little bit of thinking on that one just to get a better idea of what i actually need in the application state so this is kind of the tree uh the decision tree model in my mind for how this whole thing works uh so basically you start with a whole data set um which will look kind of like responses this guy here uh just an array of objects each property in the object represents a column in the data set uh this will of course this is just some dummy data that will be replaced with the actual salary data so that's the whole data set is the responses so let's go ahead and say responses now then the next thing that we do is for uh for each of our properties you know like outlook we calculate the variance and you can see that in the split variances so you can see that when we split the outlook variances 60.56 the temp variance is 19.4 the windy variance here's our windy is uh 50.93 and uh you know for those that are joining on this uh particular stream um the when i'm saying variance what i mean is for our target variable which in this case is hours played when i do the salary it's going to be the salary will be our target value basically your x axis in the histogram and we're looking to minimize the variance of that particular uh target variable because that indicates that uh you know if we look over here temp has a variance of 19.4 which is smaller than all the other ones so that indicates that temperature has a more significant impact on hours played than any of the other properties and that's the question we're trying to ask about the salary is which properties impacted the most so first of all sorry lost my train of thought there um so basically we're going to split it on the properties here's the potential values for outlook and we actually experiment with splitting it out on each of the properties to determine which one is the lowest once we determine which one's the lowest we split our decision tree out and then for each node so for the data set where the outlook is rainy which would be one two three four five records so this the data set on this node is now only five records then we want to split that data set and calculate the variance by each of the other properties so that is the method of building a decision tree and we're i'm not looking to just build a decision tree because i actually want to step through and look at each little cut and segment uh you know to to see what each of these pieces of data look like you know because we may find that uh we may find that that as we drill into the data we may find things that the variance doesn't pick up for example if you have um you know on a histogram if you've got let's see if i can do like paint or something like that let's say on your histogram you've got a uh a curve you know normally you've got the normal distribution curve like this but what if there's a second bump down this way on one of the resulting graphs well your variance is going to be calculated on the entire set so the data set as a whole is not homogeneous but we can still see a pattern in it and that's why i kind of want to be able to quickly trill into other attributes you know um just because our selection criteria doesn't specify that a particular value is significant doesn't mean i don't want to look at it you know what if certifications have no impact whatsoever that doesn't mean i don't still want to look at the uh the certification graphs um and that's why i'm not just creating a that's why i'm not just using a library that builds a decision tree for you because while i'm following the process of a decision tree i actually want to look at some of the nuances in between in the construction of that decision tree and so i'm kind of having to do roll this on my own a little bit so with that let's look at what the application state is actually going to need to be so of course we do need responses that one's going to be kind of important because that's our actual data set there's no getting around that one we also are going to want to have a filter and this is where i'm actually going to have to make some changes like i said because right now filter is not in the application state it's just something i'm passing in an action and i think that may have been a mistake um i think that may have been a mistake so we're going to revisit that i think that the filter itself should actually appear in the application state itself uh let's see what else do we need so as i'm going through uh i'm gonna do the splits i have the functions to calculate the splits [Music] and i've got then we're going to apply a filter so we'll select this node which will say filter my data set down to outlook is rainy so in fact our filter is going to be responses is going to be an array of objects filter is going to be an object of property name and a selected value and it's going to be a series of those properties so basically if i select at each node if i select rainy then i'm saying outlook is rainy uh if i then were to select the hot in order to split off of this one i'm saying outlook is rainy temp is hot so you can see how i would build a filter object out of that whereas last time i had it as a function and that should hopefully allow me to more easily build the filter what else do we need um so we're going to want to show histograms what am i going to need for the histograms well i'm going to need in order to build our histogram i'm going to need to provide a oops number of bins i'm going to need size of bins maybe i might need those um and that's going to let us calculate the values that we need will be able to count and sort everything into those bins now the question is which histograms will be displayed so i'm going to need to have a so i'm going to turn around i'm going to filter it then i'll click a button or something to split it out and i'm going to have hot mild and cool and when i have rainy selected i'm going to want to display the histogram for rainy and then the histogram for hot mild and cool um which means because i could split out on multiple properties so i'm going to have to have a selected property display histogram for property so actions wise we'll need gonna need add to filter are added to filter actual do filter added filter removed try and keep things fairly simple to start with i'll need and i think i already have this one app loaded or something to that effect and i'm going to need an action [Music] for um so we'll actually condense this one down to histogram config and we'll just do a histogram config changed else histogram property selected okay so these are the actions i think i'm going to need that'll let me change my histogram config that'll let me select my property app loaded will be my initial setup filter added filter removed and that should give me what i'm looking for to give me the basics and then i should be able to derive data based on that so let's start making some code changes around this to start out let's hit up the app.js so the responses stays but the property split variances we're actually going to remove i'm not going to remove its code right now because i do still need some of those calculations next let's come in here and we're going to update some of our actions and action types so originally i was planning on doing a responses filtered and i think it kind of decided against that one so let's strip this guy out here we go all right so let's add our additional types filter added and and pardon how slow i am with typing filter removed i've got app loaded already there see if i can just do it this way and histogram property selected and this should hopefully give me what i'm looking for all right so then we need to have our we need to create our action creators so that's going to be filter added and as i said for the filters we're going to have a property and a value because we're going to filter a property like in this case we're going to filter outlook by rainy and then we'll split off of rainy from there so return action types dot filter added and property is going to be property this is so much boilerplate and i hate how much boilerplate it is and i'm sure there are faster ways of doing this um but right now i'm not aware of them uploaded filter added filter removed and for filter removed all i'm going to do is do property and that'll remove it and then we're going to do another one for histogram config changed and we will pass i don't know what i'm going to pass for that one yet i don't know what that's going to involve we'll get there um now and i'll i'll of course update some of these action types here in a minute all right and then last we need histogram properties selected that one i do know we want a property okay so now we need to go back and update some of these action types filter removed for this one histogram config changed for this one histogram property selected for this one then we need to add a few of these to the exports instagram property selected okay so now our actions are set up you know and one of the things i really like about this setup despite the boilerplate the boilerplate does drive me up a wall a little bit i can probably find a way to macro it or something like that but what i like about it is that it gives you a nice easy way of determining what actions you can perform in the system without having to go look for a bunch of on clicks now of course as this list piles up you'll have to refactor the code and move those around a little bit but it still gives you a nice easy way of determining what actions you can perform in the system and especially if you have a way of joining those different files together when you do end up splitting them out it really helps you keep track of the commands you can issue all right so the actions are set next up all right so now that i got the action set now i need to start adding some reducers in order to handle these so let's see let's start with because i've already got responses down and i don't think i want to change that one responses reducer just returns that on app loaded and returns previous state otherwise um yeah so next up we're going to do filter set up our export and then we're going to turn around and do the filter reducer previous state action and what we're going to do is if action we also need to do some imports import i think it's action types from oops from dot slash actions.js if action dot type is equal to action types dot filter added so this particular reducer is going to have to handle action dot type equal to action types filter added and filter removed and then of course our fail safe we'll assume that it's going to return the previous state um and then we need to so for filter added what we're going to do is um let's see new filter so new filter is going to be equal to and let's see i need to look this one up so this is where the es6 gets kind of fun for me uh es6 object spread so i know of the spread operator but i really haven't used it much service now being es5 based and all um let's see okay so basically i can spread the original object out so what we want to spread is previous state so this is going to make a clone actually i don't even think i need new filter on that one because what i should be able to do i should be able to simplify this and just do return that object with previous state and um and there's also a syntax for es6 dynamic object key and that's going to be like this guy here so basically what i can do is dynamically set an object key so normally what i would have to do is create an es5 i'd have to create an object uh and then assign a new property afterwards by doing uh you know if i had the new filter dot or new filter square bracket action dot property is equal to action dot value is what i would have to do in es5 but since i'm doing stuff outside of servicenow i can use es6 which lets me use this new syntax i think can i use dynamic property key i don't know i guess we're going to find out though so what i want is action.property and that is going to be assigned to action.value and that will add a new filter uh to my filter object and ah and when removing uh let new filter equal to and we're going to do the spread operator again previous state and then we're going to do a delete new filter action.property and i think that should do what i need and then return new filter and for those who are unfamiliar with redux uh and and how it works uh you may be somewhat confused by why i am creating new objects why i'm not just manipulating the previous state and returning it out and basically by keeping the data immutable that is not changing the original data and instead making a clone making a copy of it i can actually more easily keep track of history you can more easily implement undo redo type functionality but most importantly it is easier to reason through what is happening in your application since you can't change the original values all you can do is return new values uh you know i can come in here and when i'm logging stuff out i can see what the state was before and then i can see what this what what the states are after so you can see here uh humidity is 81 but then it goes down to 20 after i take this action and normally if i had mutated these values what would have happened is as soon as i expanded this it would show whatever the current state is and because there's only one copy of the object both of them would show the exact same values but by cloning i have two different objects and i can output the previous values and the current values and you can basically see how your application state changes over time and you can see how the different actions influence it so with this set up i now want to export that reducer and then i want to come back to my app and we are going to import the filter reducer from dot slash app slash filter.js and we're going to say the filter is filter reducer previous state dot filter and what do we got action all right so um let's see what we've got uh app.action dot app slash actions does not provide an export named responses filtered oh i gotta get rid of that one and reload responses filter is not defined so i'm dispatching something that doesn't exist right now and reload and there we go cleared out those errors uh how's it going guys i see some some folks joining and watching in welcome all right so i should have a filter on this one now which is undefined expected because it's just going to return the previous state unless i issue a new action and if i go back to my actions i'm going to just import all of them just import everything from actions i don't think that worked it didn't like that identifier expected uh let's see import all oh because that's for named x uh named imports i want that one as name as actions from there we go okay so now i should be able to do store.dispatch actions dot perfect uh what we want is filter added and we're going to add a filter for outlook so let's say we want to filter where outlook is rainy now the net result here that i am hoping for is to add that property app loaded is not defined oh because i changed my imports update that refresh there we go okay so app loaded fired filter added fired so our filter is undefined and now it's outlook rainy and the last thing i want to try is let's see if actions dot filter removed let now let's remove that filter on outlook and so these dispatches are going to happen in user interface actions so on click stuff like that but right now i'm just testing so now new state is filter undefined after we add the filter the outlook is rainy and on the last one when we remove it filter is blank perfect now one last thing i want to change on our filter is if it's undefined i want it to default to an object i never want my filter to be undefined and that'll just help with some consistency in the code without having to null check uh reload everything still works we're good okay so that gives me my filter uh what's next so that's filter added and filter removed uh histogram config changed we'll get to that one and we will get to the histogram property selected in a minute what i wanted to do next is i want to adapt all right get rid of that one get rid of the filter reducer get rid of responses variance split all right so variant split was originally part of the application state uh you'll notice that i was passing in the entire application state so when we look up here in each of these other reducers i'm only passing them their particular slice when you start getting to the point that you have to share slices with one another that's usually a red flag that you may have an opportunity to simplify your application state and that's exactly what i've done here originally i was passing an action in i was processing a lot of data and i was adding that process data to my application state and really there was no reason for that the application state should be fairly simple um any of the calculated values we can use what's called a selector function um which in some ways is not all that familiar or al that not all that removed from a reducer however there are some differences so first of all we're going to rename this guy and some people prefer select i like get for for my selectors so we're going to say get variances for split um okay so we passed the application state in uh we were filtering okay so let's actually do that one first um for now let's do this i'm going to create a separate file for just the selectors just to kind of clear my mind a bit so the first thing i need to do is i need a selector for get filtered uh we'll keep the terminology consistent get filtered responses so we're going to pass the state in and getting filtered responses means taking and actually i have this one over here already if action.filter filtered responses means doing something like this i don't want to make any changes to that guy all right so let's bring this guy over all right so filtered responses we are actually doing a filter on we're going to be doing a filter on and previously my filter was a function so i do actually have to change that filter response so basically we're going to do an array.filter and we're going to pass the filter function so i don't need any intermediate variable because all i really have to do here is just return and we're going to say filter we'll call it filter response all right so in this we have to take into consideration the application states we have to take into consideration which property filters we have and we're basically treating this as an and operation so what i want to do is we will default to a return true so include it good morning druv how's it going and so we'll default to return true we're going to need a while loop so for let i in state dot filter and just woke up you're just waking up and i am going to be nearing going to bed soon i have to remember how this 4i n works in javascript uh test one uh so a equal to that so we'll say a f4 let i n a console.log i what do we get okay cool so that's going to give me the keys all right so 4i in state filter and what we're going to do is we're going to say if response i is not equal to state dot filter i so basically what i'm saying here is if the uh response if our where's my data responses so if i have a filter such as this one here where it says outlook is rainy what it's going to do what this function will do is it will say it's going to iterate through all the responses and if the outlook which is rainy here is not equal to what we have selected in the state filter return false and so basically it's going to iterate through each object in the filter check it against our response object and if any of them don't match then that one's not part of our filter data set um if it clears all of them it returns true and it does get included now one thing that i can do is i can uh using our little es6 module here i can actually memoize uh this particular function and i want to say that there's actually something out there that lets you create a memoized function and implementing memoization uh you know what i'm not going to worry about it right now because my data set is honestly pretty small but one thing that i could do for performance optimization is i could turn around and i could say var state and i could uh or we'll call it memo state var memo [Music] filtered responses and basically what i could do is when i call this function i could ch i could do an initial check and i could say if state is equal to memo state return memo filtered responses and skip all of the filtering and processing down here and for large data sets that little performance optimization could be really important my data set is not large so i'm not going to care about it right now um and like i said there are there are generic memo memoizing functions out there that basically lets you uh it would let me pass get filtered responses in and it would return a memoized version of the function so um it's it would not it would be trivial for me to come into this module later and convert this to a memoized version if i needed that performance improvement right now i just don't so we're going to skip it get filtered responses all right so that's the first selector that i needed was get filtered responses the next one that i need is going to be get variances uh and we'll actually call it get split variances and so once again when i so the the getting filtered responses means that when when i move from the whole data set down to uh a specific part of the data set when i'm moving through the decision tree uh get filtered responses will let me filter down to that data set get split variances then is going to calculate uh it's going to go through each of the properties and it's going to calculate um what the variances are for the resulting data sets um so with that in mind i actually did have that one back here and i did have my little library variants here where i've got a bunch of statistical functions that i created uh prior to part one uh before i started recording all this stuff and all it is is mean variance calculations and a couple of utility functions so get variances for split variances is an object so we create that object and then we say what is response properties that is coming from data.responses okay so that's part of my configuration um that's fine i'll import that at least for now i could probably put a bunch of this stuff into a config variable on application load but for now because i've already done it this way i'm gonna stick with it and if we need to we can clean it up later and put it in the application state um alright so then filtered responses is equal to all right so the first thing i have to do is filter my data set so that is going to be this guy here next we're going to do uh response properties so for each property when i come over here response properties is a is basically just these outlook temp humidity windy hours played essentially it iterates through the uh through the objects and it fine of the first one and it gets all of the object keys and then it will exclude the target property [Music] so response properties for each property variances add a property calculate the two attribute variants for it so basically this is splitting up our data set so if i had filtered down to rainey and i was calculating the two attribute variants on the temp property it would find hot mild and cool as the possible options so temp could be hot temp could be mild temp could be cool and it is creating a variance object for each of those and uh assigning the sh the the variance of the target property which in our case is the hours played when i switch this to salary it'll be the salary and and then it's assigning that to the variance property and then we return variances okay so then we'll export this function and i'm going to come out here and i'm going to import get split variances from uh dot slash app slash selectors dot js and we're gonna do a quick console.log get split variances and i need to be able to get state um i can't remember if i added that one in my poor man store or not dispatch subscribe i did not okay so we're gonna add a function down here get state return state and this is my poor man's redux store if you missed out on part one um i've been using this one uh well the es5 version of it i've been using in a few different um projects here lately and i gotta say i've really enjoyed it so store.getstate and then we'll come back here we'll reload an error will throw store.getstate is not a function but i thought it was let's see store dot get state create store should uh let's do a full reload okay full reload did it it was caching it was caching the previous version of the store apparently filtered responses is not defined okay and that is in get filtered responses uh not that one in selectors get filtered responses filtered responses is not defined oh my bad this needed to be state dot responses calculate to attribute variance is not defined because i did not import it import calculate to attribute variance from that's going to be dot dot slash libs slash variance.js and then we will reload cool ah and there we go we've got our uh we've got our variants okay so we'll jump back to the app real quick and we'll kind of show you this gets this should get us caught back up to where i was last time uh before i decided to make some changes to the application state so what i'm going to do is i'm going to output before that filter is added after it's added and then we're going to come down here and we'll remove the filter afterwards reload okay so [Music] before we add the filter and this is no filter meaning we're calculating the variances of the where's the responses we're calculating the variance of the hours played across the whole data set and these are the variances if you were to split by each of those properties so if i turn around and if i split this data set by outlook uh then basically what you would do is you would calculate the rainy variance the overcast variance the sunny variance multiply each of those by the probability of that occurrence so for rainy it would be 5 out of 14 i think so 5 over 14 times the variance of that slice of the data set 1 2 three four over fourteen times the variance of that slice and then uh one two three four five over fourteen times uh that slice of the variance and then you add all that up and that's where you get this 67. do that again for temp do that again for humidity do that again for windy and that tells you that outlook is the lowest variance so outlook is the one we should split by so we add a filter which is our we're splitting uh we're we're actually splitting our decision tree and in it we are splitting by the outlook property we're selecting the outlook as the split and we're saying that we want to filter down to the rainy note so basically those at what those actions look like as we start here we decided on outlook we select the rainy one and then we run our calculation for the splits uh for our variance splits again and you'll see that temp is the new winner so once we have selected for down to just the rainy outlooks just one two three four five the next split would be temp that is temp is the next greatest impact on the hours played so that's now working what we need to do next is start thinking about the histogram and how we're going to build the histograms because ultimately with this i can calculate the variances and i can essentially between those actions i can walk down the entire tree of properties on survey responses and figure out what let's say the top five uh impact uh the the which five questions most impact uh the salary then i can turn around and i can dive into how much did this one impact how much did that one impact and we can analyze each one independently but the visualization that i want most is that histogram so to get the histogram grow going we have to add some new uh reducers so histogram js and for this one i'm going to first we'll set my export at the top and we'll do the import and we're going to do um what do i need i need histogram change histogram property selected and action types from dot slash actions dot js all right then we need to create a histogram config reducer which is going to take the previous state the action and it's going to by default return the previous state and let's see histogram config really honestly i think what we're going to do is quite simple on this one i think what we're going to do is just action dot type is equal to action types dot histogram config change so if we have a config change i'm just going to return action dot config i think this is actually going to be the easiest way because then i can come back here i can pass config and essentially i'll just always create a new config object so and i can actually handle that in my action creator by saying a spread operator config and now i'll always have a new config object now if i do complex configs that could potentially throw some issues uh if i'm not careful uh but for now this is going to be a quick and dirty way of not having to think too much about what that config needs to be right now uh and once again i'm gonna do an or ensure it's an object and we'll kind of do the same thing here just in case so that the config is always an object so that'll handle the histogram config then we need the selected property reducer previous state action and we're basically going to do much the same thing for this reducer if action type is histogram selected return action dot property the property that we selected and i'm not doing anything as far as that goes and uh previous state if and if that one's we may have to do some undefined checks on that one but that's okay export both of these and then we're going to come over here and we're going to import that reducer and histogram config producer from dot slash app slash histogram dot js all right and we're going to say histogram histogram selected property so that's the property basically when i display a histogram i want to be able to select you know this data set that property and it'll generate four histograms one for this node and one for those three nodes to show me the the the parent and the resulting splits so come back over here previous state dot that guy action and then we need histogram config and we're going to say histogram config reducer and previous state dot histogram config and action okay and all right we'll get rid of these console.logs for now and we're going to do store.dispatch and these are again these these are just testing actions dot oh actions dot histogram config changed and we'll just give it a test property for now dispatch actions dot histogram property selected and we'll say outlook that's fine okay save it reload everything and we get an error uh error aborted not found app histogram.js survey analysis tool yeah i don't know about that chief it should be there ah historic gam histogam spelling is everything that's why i should have used the autocomplete there we go all right so let's take a look no filter no histogram config to mention histogram selected property is undefined it remains that way as we add the filter and it remains that way as we remove the filter and then we update the config and then we select the property outstanding all right so that gives us the application state that we then need in order to compute our histogram um let's see now this is where things are going to start to get a little bit complicated um so essentially what i'm going to have to do is i'm going to have to come back to here um get histograms now um this is going to be a selector that accepts state now basically what i'm going to have to return is going to be something like this we'll have a parent histogram which is probably going to be an array of bins in order so uh essentially let me pull up paint and we'll kind of sketch this out so generally with a histogram what you'll have is you have a series of bins on a bar chart and usually they resemble you know sometimes with some variation but overall you will usually see some kind of curve normal curve assuming it has a normal distribution of course that's not required you can have multimodals and such but for now we're going to assume that we're going to see a lovely normal distribution i have no clue what the results going to be in all reality but you know this is what you'll have in a histogram and you know if i were to draw the chart this side here is going to be the salary so that's the y-axis y-axis is the almighty dollar or select your country's currency here and i do have some ways to handle um oh shoot man i didn't even see you uh drop in there uh gosh remind me what your real name is mhz not mentally sharp enough to apply this to my service now knowledge tonight but seriously appreciate how much detail you're giving even though not servicenow the level of detail will help to apply this later yeah and you know i'm i would honestly have loved to have used servicenow but in the name of keeping the data on one computer and one computer only minimizing risk minimizing the the the risk of somebody else getting access to it somehow um i opted to keep it on my own machine and you know i don't have servicenow on that machine so i was kind of up a creek and what i do like about what i'm doing with the es6 is i i feel like i'm practicing a little bit for ux framework i haven't used it much but i know that uh react uses um es6 uh extensively in it and i know that there's uh there's quite a lot of the the import export and that sort of thing that you can leverage in there so i'm hoping that i'll be able to reuse some of this knowledge um and if nothing else this whole project is really just one big data transformation um and you know this particular architecture that i'm using with redux is something that i have been exploring experimenting and using in multiple other projects uh it started out with triage which is on servicenow share and we'll take a look at that one real quick and share there we go so triage is on the service now share now triage uses a early version before i really started to understand um what made react and react redux tick but so this little question and answer guy it would step you through questions and this whole thing is tracked using a event history model as well but it's more of a event model where everybody subscribes to everything uh so it tended to get a little bit messy in the code a little bit more than what well frankly it's a lot more messy than what i've refined it into now um but it is less messy than other approaches i had used before so it was an improvement but not quite to where i've gotten now now i've got this store like i said this poor man's redux store that is you know i mean you can see here it's like 76 lines of code in total um it's pretty compact there's a very simple dispatch function very simple uh observer pattern with subscribing there's a couple differences between what i've done and uh redux you know first of all i don't support any plugins in mind because it does exactly what i want second of all i can do i can handle asynchronous actions like server side fetches and stuff like that i can handle it in dispatch asyncs which i'm not actually using on this project i don't think but it is something that i am using on ui flow which is the um it is everything i wanted triage to become but better uh and it it does use this particular store yup yup yeah it's it's there's a lot of similarity between what i'm doing here and the ux framework there's some different terminology but the concepts are the same the ux framework does use a redux store itself at least the last time i checked it's still using redux behind the scenes um so there's a lot of similarity uh with that particular approach so i feel like i'm practicing for it if nothing else and like i said i've been using this in service portal for numerous projects now and i find that this method of uh interwidget communication uh plugging this store into an angular provider and then letting widgets communicate through that provider is just a revolutionary way of handling uh interwidget communication and i actually did a talk on interwidget communication a few years back before i had learned this particular approach and this one replaces all the others for me i don't use any of the other techniques for anything anymore this is the only architecture that i've used on any form of complicated widgets set up on service portal ever since i came up with it or i didn't come up with it smarter people came up with it i just hijacked it and wrote my own version of it i wasn't smart enough to come up with this architecture i think it was uh facebook uh the facebook engineers that came up with this sucker absolutely brilliant technique it took me months to actually understand what they were doing and why but now that i get it just it's just an absolutely mind-blowing technique um okay so back to the histograming here uh right i was describing the histogram so the y-axis is going to be the financials axis uh or no sorry i completely botched that i completely screwed that up the bins are going to be the financial access so what we're going to have is we're going to have the financial access there we go the financial axis is going to be down here and what you'll have is like from zero to making up numbers here uh zero to a thousand okay and then uh one thousand to two thousand two thousand to three thousand of course that's going to be far too low for the ranges we're actually talking about but each bin is going to be the same size there's going to be a set number of bins and the y-axis is the number of people who responded who fit into that bin according to how we've filtered the particular data up into that point um so you know and again that's really the whole model here is that you know if this curve was if this curve describes the whole data set everybody's salary around the world and then i wanted to determine whether or not say the itsm certification was uh impacting well if i came up with a curve that looked like this i think we could probably argue that that's not much of an impact compared to if the curve was suddenly this where everybody with an itsm cert uh is making the buku box you know um so the idea is that by filtering the original data set down we could turn around and we could determine how the distributions change as we filter the data as we select for certain criteria and that should help us identify which criteria is most important if you want to pursue a higher salary now of course some of these we may not be able to change you know a lot of folks from india were very concerned that you know they're underpaid even when uh factoring for cost of living we're going to check that i've got some tools that i described in part one where i can factor cost of living out again smart people came up with conversion factors from other currencies to dollars that factor for the difference in currency value and the difference in uh the the cost of living and it kind of takes all that into consideration and tells you what the uh purchasing power of that unit is in dollars and then of course i can convert that back to your local currency um so you know if i select for your geographic location for some folks especially if you're on the low end of the totem pole down here uh you know if you're sitting down here getting getting paid uh pennies on the dollar and you happen to be and we factored we what we filtered on was geographic distribution well you might not have the power and wherewithal to change that for yourself um you know so some criteria you might be able to pursue some criteria you won't and i plan on looking into each of those aspects from an analysis standpoint i want to do one analysis that focuses on of the things you can change of the certifications you can pursue of the experiences you can get the pieces of the platform you can focus on which one's going to drive your value then i want to do an analysis for you know each of the potential biases and discriminations that exist in the world are those impacting our industry from a salary standpoint um you know and i'm hoping to look at all of those different angles and this is how we plan on doing it so count of people bins of dollars and that brings me back to the histogram bins where we're going to have a parent which will have an array of bins and each bin will have a count in it and the parent in this case would be like rainy and then you will have children which will be an object of arrays so let's say hot would have an array mild would have an array and cool would have an array in terms of my dummy data of course um and so this would allow me to produce a histogram for rainy a histogram for hot histogram for mild and a histogram for cool now we're gonna have to do some filtering some more filtered responses in this particular function we're going to have to do um some calculations that in my library i don't have yet i already had calculate two attribute variants i don't have um you know computing a frequency distribution uh i don't even have the bin count or the size of bins factored in so these are all things that i'm going to have to figure out how to implement in order to get the histogram distributions i'm going to do that next time i'm actually going to hold off at this point i've got my selector started i'll do a little marker here to do next and we'll focus on this one next time and i know after part one i said we focus on histograms and uh it feels a little bit like i just procrastinated an entire session but i do actually like the structure of the code i've got here better my state is a little less dependent on other state i've factored out the computed state into selectors and this feels a lot better to me overall once i get the histogram calculations down once i have this object able to be computed then i begin building the ui components and i'll be able to actually start putting visuals to this and bringing some uh visualization libraries or maybe i'll just use html to draw the uh the histogram uh i guess it depends on what i can find library wise for what i'm wanting to do um but i will say that this is really starting to come together we're getting a lot closer to being able to analyze this data using this tool having the variances uh all already is really solid because that way i can at least get a sense of which ones to select which ones should have a greater impact on salary and once i do get to the point of actually analyzing the data what i'll do is i will update the responses array here with the salary data i'll do that off video and then i will pull up the tool and i'll actually walk through my analysis live uh for better or for worse and we'll take a look at what the different distributions look like together uh and i'll build out you know build out and draw my conclusions and then write up uh more formal white paper on it and publish that out um let's see checking the chat over here uh oh well didn't even realize you were putting this into angular providers so yeah uh before i sign off for the night we'll actually take a look at that one um i think it's this guy so this over here is not currently angular providers this is all just raw static website stuff however i have been using vs code for servicenow so um one of the things that i've got here is this is for the triage application you can see i got triage and i got ui flow in here this is using the vs code plugin i have been using nothing but this ever since i started for all of my service portal development at this standpoint or at this point i i just i am in love with this plug-in it's amazing um basically it lets you use vs code to edit your service nail code so this here is the triage application and you can answer questions and step through and everything else now this one does not use the recent version of the store as i said but you can see the history and you can see some early state.history.push is kind of the early precursor to my dispatch function so there's a lot of similar capability in here but one of the big one of the big mistakes that i made in this one was that i leveraged too heavily on the history so you will see in most of my so this is a client script uh this is the client script for this particular widget so if i pulled um that's weird why won't you let me do the thing oh probably not logged in let's log in yep not logged in okay there we go and then we'll reload this guy and then i'll pull up the widget editor so this client script here this decision assistant or sorry this this client script that's using the decision assistance store is this guy over here and uh this update viewstate function what you'll see is i do a where is it so anytime i trigger an event i am calling the update view state function so i'll turn around and i'll issue something to the store and then i call an update view state i'm not letting the store handle the notifications and so what i'm doing is i'm pushing data to the store and then i'm reading data from the store and it was a little more complex and the other big mistake was you'll see a lot of this dot history um i'm storing the state in the history and i'm doing kind of a event sourcing model in this one and it makes the code really messy it makes the code a lot harder to read but in my new fancy which is ui flow you will see let's see this would be service portal angular providers in my server data you'll see somewhere up here all the way up here you will see this store module and there's my dispatch function and there's my subscribe and there's my get state and so you know going through all this um this is the es5 module version um of what i am using over here for my store it's the exact same code just switched from es5 to es6 but this is actively being used in this particular widget and i've got a few others that i'm using it in but to show you what this one is and this is part of glidefast's fastgov offering um let's see what did i call it again oh ui flow so ui flow is basically if record producers and order guides had a baby so when i pull this up i have a multi-step process where i can fill out forms i can add multi-row multi-row items and next and then i can hit submit and so this whole ui flow here was built out using this data model you got views views are made up of variables so view is kind of like a or sorry ui flow is kind of like your record producer view is kind of like a container variables are equivalent to variables you have actions which are these buttons down here and you have ui flows sorry ui flows are the i already mentioned but when i go back up to the ui flow then you have transitions which is when you click an action this is what happens and you can run scripts that take a producer variable and work just like record producers and you can do that at every step in the process um so i can do it on load i can run a script again when i hit next i can run a script on submit to insert a record and so i can generate as many records as i want i have full control over the process and it is a multi-step order guide like behavior what's really cool is that ui flow actions and ui flow form these are actually different widgets they talk to each other through that store object um so if you know in let's talk about service catalog if i wanted to move my service catalog buttons well i i can't i mean i could if i wanted to go in and write some new custom service catalog macros but i can't just move the buttons wherever i want um with ui flow however because these are two different widgets i could just drag this up above the form and now my buttons are on top or i could move these buttons off to the side and add a little css and vertically align them so i just got the question is ui flow a project that's out there available for folks to look at code sadly no so this one is a glide fast proprietary project triage is its predecessor so the closest you can get to looking at its code is by looking at triage's code i will also be publishing this uh or not this this project so you will be able to see um the the the salary survey tool which has a lot of similarity to how the ui flow works and that way you can still get a look at the code you can get a look at the architecture ui flow is the same architecture it is just infinitely more complex on the internals it is thousands of lines of code um but ui flow is a proprietary one for glide fast uh and basically after triage got a lot of attention from a lot of different people who wanted to use it uh and started taking up um there were more requests for features than what i could keep up with in my spare time and so we looked at how we could kind of make a a best of both worlds sort of thing where we produced an application uh this application is part of our fastgov offering for for government services and we're looking at how we can integrate it into other things as well um i don't know how exactly all of that's going to work yet my hope is that we're going to get it into as many hands as possible um and to be quite honest we've already told servicenow that you know if this is something that they wanted to use we would be happy to work with them on helping to make something like this base platform because this is is a really powerful tool uh that you know would be a great addition to service catalog would be a great addition to csm uh especially with some of the public forum stuff that we're looking at adding to it for some of our government customers you know we've invested a lot in this technology and it's really really powerful and we want to do everything we can to get it out to as many people and of course you know we don't want to uh lose our investment on on putting the the money into building this thing um but you know we also want it to have maximum impact so we're just trying to work out how to make the the business side of it successful while also getting it into as many hands as possible um but the architecture is using this store as an angular provider yeah yeah yeah and that's uh that that i he said uh he heard me say glide glidefast after he had asked um yeah you know got gots to pay the bills [Laughter] so um but we are working to try and get that one out there for folks um and i don't know maybe we'll do kind of an open source model and a closed source model maybe we'll do an open source model with you know paid support you know paid enhancements i i don't know exactly how we're going to work it but man this ui flow is just it is it is too awesome just to leave sitting on the shelf uh for the folks that are out there already using triage because there's a number of government customers out there uh who have reached out to me who have installed triage who have been exploring triage um we're hoping to be able to get this one out to you guys as well because this is really going to kick things up a notch um and i know a couple of our customers who are looking at using triage right now who may see this and be like they might blast me tomorrow why have you been holding out um but i this this has been a lot of fun to build and there's a lot of power behind it we've been partnering with one of our customers in building this out for their needs because building this is going to save them money in the long run for a lot of the stuff that they were wanting to do so they they partnered with us on on building this out and uh this is the ui flow honestly is one of the most challenging things but also one of the most amazing things that uh i've built my career so far i've i've absolutely loved building it and uh it really hasn't been just me it's been a number of other folks at glidefast uh that i've been pinging off of you know justin bernie megan of course my wife sarah because i bounce everything off of her robert webb you know all of these folks have really contributed into helping to make this what it is um chat we've got yeah it's an interesting variation on the component state model stuff like what they're trying to do with now x yeah the i really like where now x is going i wish i i i wish i spent more time with it but you know my space is largely customer service and you know end user so with now x being heavily focused on internal uis right now i haven't gotten much time to play with it i've been spending my days in service portal um but hopefully in the coming versions of servicenow all the rumors are that they are implementing a portal style bill well they already have the ui builder but you know word on the street is that they're going to be creating a portal-like experience and user-like experience that uses now x and hopefully with what i have been doing over here using the store dispatch methods um some of the react playing around that i've done and a couple of other things hopefully i will be equipped to make that transition when we get there um but yeah it it really has been fascinating uh but at this point it's uh 11 o'clock for me if uh if sarah's not already in bed uh she probably wants to be so uh who am i kidding she she'd go to bed if she wanted to she wouldn't wait uh so if that's not a no vote of no confidence she is definitely awake and shouting now [Laughter] she's giving me crap now um but so at this point i'm gonna go ahead and sign off i'm gonna call it and uh next time we are going to dive into getting these histogram selectors up and running um so thanks everybody for joining in i hope you enjoyed it and hope to see you next time

View original source

https://www.youtube.com/watch?v=BUWNPJfMGgU