Professional Documents
Culture Documents
JUL
AUG
2016
shutterstock.com/McIek/dotshock
han
Less t
$ 1day!
per
Affordable High-Tech
Digital Escrow
Tower 48 is the most advanced and affordable digital escrow solution available. Designed and built specifically for software and other digital
assets, Tower 48 makes escrow inexpensive and hassle free. Better yet, as a vendor, you can turn escrow into a service you offer to your
customers and create a new revenue stream for yourself.
Regardless of whether you are a vendor who wants to offer this service to their customers, or whether you are a customer looking for extra
protection, visit our web site to start a free and hassle-free trial account or to learn more about our services and digital escrow in general!
On Culture Fit
For an industry that prides itself on its analytical ability and abstract mental processing, we often dont
do a great job applying that mental skill to the most important element of the programmers tool
chestourselves. Its a staple of the modern software development interview: the culture fit portion.
In many ways, it remains the last real interview production where it will operate entirely without Researchers from the computer science depart-
part of the interview. Unlike a number of other any additional input from us. ments at Cal Poly, San Luis Obispo, and North
positions (sales, marketing, management, and so Carolina State University, looked at around
on), a software development interview is usually Having said that, though, the nature of the inter- four million people who logged on to Github
chock full of technical parts that have far more view for a position in the orchestra is not all that on a single day1 April 2015. The team
binary elements to them: You either know how to different from that of interviewing a software de- found that 78.6% of pull requests made by
use MongoDB or you dont; you either know how veloper. The orchestra member clearly must have women were accepted compared with 74.6%
to implement a quicksort or you dont; you either a level of technical skillcan you reach a high of those by men. However among users who
know how to code a binary tree at a whiteboard C on your instrument, can you demonstrate an were not well known within the community,
with no help from Google or StackOverflow or ability to sight-read (that is, play music having those whose profiles made clear that they were
even your other teammates when you will never never seen it before), can you adjust your style women had a much lower acceptance rate than
do this again in your life unless you interview and interpretation of the music to match the di- those whose gender was not obvious.
again or you dont. rection being given by the conductor, and so on.
And for years, orchestra managers have main- Still not convinced?
But then, once your technical skill has been de- tained that a culture fit is a necessary compo-
termined, theres still the notion of culture fit. nent of an orchestrathat the various members Researchers from the Paris School of Econom-
Will you get along with the other team members? of each section must have a certain emotional ics and Stanford University sent out fake re-
Will you be able to share in the jokes? Will you be connection to each other in order to fit in well sumes to apply for real jobs in Paris. All six
able to be a positive force within the team? Or will as a whole. resumes detailed identical work experience.
you be the prima donna, the annoying one, the The only differentiator was language skills on
one that just doesnt seem to fit in with the rest All of this is why this recent study, as described two of the resumes. The two French-sounding
of the crowd? This is an important part of team by a New York Times article on interviews, is so names received 70% more callbacks than the
chemistry, and so therefore a necessary part of importantand disturbingto read: other four namestwo of North African origin,
the interview. Are you a good culture fit for this and two that sounded foreign, but were hard
position? In the 1970s, symphony orchestras were still to place. Foreign applicants, whether their
made up almost exclusively of white men di- specific minority group is identified or not, are
Apparently, its the last great opportunity for dis- rectors claimed they were the only ones quali- equally disadvantaged as compared to French
crimination and exclusion to happen. fied. Around that time, many began to use a applicants across all dimensions under study
new method of hiring musicians: blind audi- for both genders, and whether or not more
tions. Musicians auditioned behind screens so information is available in the application,
Building an Orchestra the judges couldnt see what they looked like, the paper found. The reason? Homophily a
As industries go, not much really seems to overlap and walked on carpeted floors so the judges preference for people who are more like you.
between the software development industry and couldnt determine if they were women or men
the orchestral arm of the music industry. One is so the women often wore heels. The Boston Unfortunately, findings like these are not lim-
very much bigger than the other, one is so clearly Symphony Orchestra pioneered the practice ited to our French counterparts. American re-
an entertainment art where the other is a staple in 1952, and more orchestras began using it searchers had similar conclusions in a study:
of industries all across the spectrum, and one has after a high-profile racial discrimination case Are Emily and Brendan More Employable than
a strict dress code (tuxedos and cocktail gowns) was brought by two black musicians against Lakisha and Jamal? Applicants with white-
while the other well, it also has a strict dress the New York Philharmonic in 1969. Research- sounding names were 50% more likely to get
code, but at the other end of the spectrum (T- ers from Harvard and Princeton took notice and called for an initial interview than applicants
shirts and jeans). studied the results; they found that blind au- with black-sounding names. Applicants with
ditions increased the likelihood that a woman white names need to send about 10 resumes to
Even the very nature of delivery is radically dif- would be hired by between 25 and 46 percent. get one callback. Applicants with black names
ferent. An orchestra practices the same symphony In fact, with blind auditions, women became need to send about 15 resumes to achieve the
over and over again for months in hopes that they slightly more likely to be hired than men. same result. (http://www.forbes.com/sites/
will deliver an amazing performance, when they (http://www.nytimes.com/2016/02/28/mag- ruchikatulshyan/2014/06/13/have-a-foreign-
will start the symphony all over again, and begin azine/is-blind-hiring-the-best-hiring.html) sounding-name-change-it-to-get-a-job/)
from the very first note, and a software develop-
ment team spends months writing lines of code If youre a software developer, and youre not Thats pretty disturbing, but the deeper question,
that collectively and cumulatively create a deter- starting to see the parallels with our own indus- for me, is this: Am I guilty of the same thing?
ministic (we hope!) result on the day when we try, its because you havent been paying atten-
run the final demo and deliver the software into tion to the news more recently. (Continued on page 73)
Columns
Markus Egger
these dynamic types from .NET, according to John. Find out how! Rod Paddock
pretty dominant cluster in the late-twentysome- departments are notoriously slow to adopt to
John V. Petersen Art & Layout
thing/early-thirtysomething range. change, and it will take several iterations of the
King Laurin GmbH
studies mentioned above before this starts to sink info@raffeiner.bz.it
24 Support Your Application Post-Launch We were, in essence, a pretty non-diverse com- in to the business worlds collective unconscious.
74 Managed Coder: On Culture Fit Production
Intelligently Using Intercom.io Ted Neward
pany, when the final accounting came in. I have But for an industry that constantly considers itself Franz Wimmer
to wonder, how much of that was just the luck of a meritocracy, I think its high time we stop wait- King Laurin GmbH
Jason shows us how to keep the development team focused on developing the draw in terms of who applied, and how much ing, and start leading. 39057 St. Michael/Eppan, Italy
while creating built-in post-launch features that keep your users happy too. was homophily at work? Printing
Its not magic, its Intercom.io.
Departments
Give it a shot. Fry Communications, Inc.
Jason Bender 800 West Church Rd.
Mediation Ted Neward
Mechanicsburg, PA 17055
Advertising Sales
32 Go In many ways, one can argue that the industry Tammy Ferguson
Theres a new language called Go, and youll want to check out 6 Editorial is made up predominantly of white men because 832-717-4445 ext 026
tammy@codemag.com
Teds exploration of it. Go ahead. You know you want to. thats the only ones who are qualifiedbut the
Github study seems to disprove that pretty easily. Circulation & Distribution
Ted Neward
17 Advertisers Index We can argue that cultural fit is an important part
General Circulation: EPS Software Corp.
International Bonded Couriers (IBC)
of employed life, but if that culture is a predomi- Newsstand: Ingram Periodicals, Inc.
42 Introduction to IoT Using the Raspberry Pi nantly white male one, the chances of bringing Media Solutions
Special tools are necessary to make the switch from clunky desktops to fluid
73 Code Compilers additional cultures in is pretty small. Why should Subscriptions
mobile apps, and if you want to give your mobile device (or your clients) that matter? Because having a diverse workplace Subscription Manager
Colleen Cade
access to the Internet of Things (IoT), you need to know about them. Wei-Meng yields better results: 832-717-4445 ext 028
and Clarence have done the hard part of researching it, and they recommend ccade@codemag.com
Raspberry Pi. Firms with diversity tend to innovate and out-
Wei-Meng Lee and Clarence Chng US subscriptions are US $29.99 for one year. Subscriptions
perform others, a Center for Talent Innova- outside the US are US $44.99. Payments should be made
tion study (http://www.talentinnovation.org/ in US dollars drawn on a US bank. American Express,
50 How to Write Your Own Programming Language in C# assets/IDMG-ExecSummFINAL-CTI.pdf) finds. MasterCard, Visa, and Discover credit cards accepted.
Bill me option is available only for US subscriptions. Back
Employees at these companies are 45% likelier issues are available. For subscription information, email
Have you ever thought that the language you were coding in lacked some
to report that firms market share grew over subscriptions@codemag.com
important tools? Vassili shows you how to write your own language without
building a compiler. the previous year. They are 70% likelier to re- or contact customer service at
832-717-4445 ext 028.
Vassili Kaplan port that the firm captured a new market. Plus,
a team with a member who shares a clients
Subscribe online at
ethnicity is 152% likelier than another team to www.codemag.com
understand that client.
CODE Developer Magazine
6605 Cypresswood Drive, Ste 300, Spring, Texas 77379
Maybe just maybe its time to rethink our in- Phone: 832-717-4445
US subscriptions are US $29.99 for one year. Subscriptions outside the US pay US $44.99. Payments should be made in US dollars drawn on a US bank. American Express, terviews. Fax: 832-717-4460
MasterCard, Visa, and Discover credit cards are accepted. Bill me option is available only for US subscriptions. Back issues are available. For subscription information, send
e-mail to subscriptions@codemag.com or contact customer service at 832-717-4445 ext 028.
Subscribe online at codemag.com
Summary
This all begs the question: How do we do this?
CODE Component Developer Magazine (ISSN # 1547-5166) is published bimonthly by EPS Software Corporation, 6605 Cypresswood Drive, Suite 300, Spring, TX 77379 U.S.A.
POSTMASTER: Send address changes to CODE Component Developer Magazine, 6605 Cypresswood Drive, Suite 300, Spring, TX 77379 U.S.A.
I think maybe its time to start considering drop-
Canadian Subscriptions: Canada Post Agreement Number 7178957. Send change address information and blocks of undeliverable copies to IBC, 7485 Bath Road, Mississauga, ping cultural fit as a candidate criteria point. Its
ON L4T 4C1, Canada.
that it have a decent story with a decent plot This was true then and its true today. When you If your website has a smallish set of users, this
and isnt too convoluted. Some of my favorite su- choose to use one of these frameworks on a proj- might not be a big deal. If your website has a
perhero movies include Guardians of the Galaxy, ect, youre adding a huge risk to the cost of de- large number of users, this could be quite an is-
The Avengers, and the Captain America Films. My veloping and maintaining your Web applications. sue and needs to be considered in your risk as-
least favorite films are Iron Man 2 and 3, Batman Here are a few issues you need to consider. sessment.
and Robin, and most of the Spiderman sequels.
Theres a simple reason the aforementioned films
are not to my liking: too many plotlines. Each of Framework Churn CODE Magazines Commitment
the films have too many bad-guys (each requiring You need to look at the rate of change that hap- As a magazine built by and for developers, CODE
a sub-plot) that the protagonist has to deal with pens on these frameworks. Every release of a Magazine will continue to explore these frame-
and none of the sub-plots is served well by the framework has a chance of causing regressions works in our pages. Well work to create content
film, often making no sense whatsoever. in your applications. Do you have adequate test- to help you make decisions about using these
ing procedures (automated and manual) to insure frameworks in your Web applications. Well remain
This is also how I feel about the current state of that new releases of the framework cause no re- agnostic to what framework we promote (for in-
JavaScript frameworks. gressions? stance, we have articles discussing both Angular-
JS and Aurelia in this issue). Well do our best
Did you see what I did there? I went from superhero to help you guide your development practices
sequels to JavaScript Frameworks in one fell swoop. Breaking Changes through the numerous plotlines being written
As software developers, we live in a world with Last year, there was quite a controversy regard- even as you read this issue.
too many plotlines, that is, too many JavaScript ing the changes being made to the Angular JS
frameworks. Lets take a look at some of the framework. As it happens, Angular-JS version 2
big-name frameworks and the catch phrases that was a fairly radical departure from version 1 of the Rod Paddock
their developers use to describe them: framework. Whats the migration path for devel- Figure 1: The dreaded multiple-account dialog box
opers to move from 1.0 to 2.0? Is there a migra-
Angular JS: A super-heroic JavaScript MVW tion path or are 1.0 developers just stuck? This
Framework is a huge risk when adopting a JavaScript frame- my login is checked against their AADs. So myeager@ ticate each user against a known list of logins. Looking
React JS: A JavaScript Library For Building work. You might need to be ready for planned awesomeco.com exists in all of those AADs. But because at the log in screen, the list is obviously an Azure Active
User Interfaces obsolescence when it comes to your framework Im using my Microsoft ID, those AADs dont store any Directory login, but which AAD? Thats not always easy to
Ember JS: A framework for creating ambi- choices. passwords; they pass the authentication through to a set know. Its up to the app, but you can get a clue by looking
tious Web applications of Microsoft ID authentication servers. Each AAD holds a at who owns the app. Here are a few commonly used apps
jQuery: The Write-Less-Do-More JavaScript record of my user name, but some of them store and verify and the AADs they use:
Library Community Adoption passwords (these are Work and school accounts) and
Aurelia: The most powerful, flexible, and The rate of adoption of contributes greatly to the some pass authentication through to Microsoft ID authen- Office 365: An AAD owned by Microsoft, specifically
forward-looking JavaScript client framework success or failure of all developer tools. Before tication servers (these are Personal accounts). for the Office 365 app.
in the world. you adopt a JavaScript framework, you might Visual Studio Team Services: AAD thats part of the
want to check Google or Stack Overflow for sup- If youve been following along, youll know that I log into Azure subscription associated with the VSTS sub-
You see, all you need to do to be a super-heroic, port requests, tips, tricks, etc. Its guaranteed all of these places as myeager@awesomeco.com, but this scription. Lets say that Im doing contract work.
ambitious, forward-looking JavaScript developer is that youll experience roadblocks when build- is how I must log into each one: The company Im working for might own the VSTS
to pick one or all of these frameworks. Bleh! Whats ing with a framework. Will you be able to solve account and its most likely using an AAD on that
a developer to do? I say: Choose very carefully. your problems quickly or will you be stuck being Work apps published by Awesome Co: Work or companys Azure subscription.
a pioneer solving each unique problem you face school account / Secr3t Visual Studio (the IDE): AAD set up by Microsoft
In the Sep/Oct 2010 issue of CODE Magazine, I on your own? My personal website: Work or school account / for the Azure subscription that youve associated
spoke about technology risk in my editorial So C0vert Visual Studio with. For instance, my Visual Studio is
You Want to Be a Consultant: Risk Management Office 365: Work or school account / P@ssw0rd associated with the MSDN subscription in my com-
Specifically, I stated: Application Bloat Work Azure account: Personal account / Ncript panys Azure account.
In his article Why Micro JavaScript Libraries Personal Azure account: Personal account / Ncript My personal website: AAD that I set up under my
As a consultant, its your responsibility to stay Should be Used in Your Next Application, (CODE Third-party apps: Personal account / Ncript personal Azure account.
current on the technologies available. This re- Magazine, Jan/Feb 2015) Chris Love wrote about
sponsibility comes with a high degree of risk. the bloat of many JavaScript frameworks and why The most important thing I learned when logging into an These are four different AADsfour different lists of logins.
Learning new technologies takes a consider- using a micro framework might be a good idea. app and finding myself faced with the dreaded AAD login
able amount of time and some technologies Many of JavaScript frameworks are fat which screen is to look at things from the apps perspective, not Each of these AADs can be set up to handle each login
might die on the vine. increases the download size of your applications. my own perspective as a user. The app needs to authen- name in one of two ways:
6 Editorial codemag.com codemag.com Azure Skyline: Azures Active DirectoryAuthorization in the Cloud 71
ONLINE QUICK ID 1607101
but sometimes I need to pick a Work or school account awesomeco.com in this AAD! This is a completely differ-
and other times a Personal account, and after I get that ent user account, with a different password in a completely
right, there are at least three different passwords that I different AAD than the one I use to log into the apps I cre-
have to choose from. Maybe what I found out will make ated at work, even though the user name is the same. Now
things clearer for you. This is not a how-to for Azure Active assume that I create a personal Web page in my personal
Directory (AAD) developers; its a how-to-use for AAD users. Azure account. I can set the website up to authenticate
against my personal AAD. Now myeager@awesomeco.com
First, whats an AAD? Like an on-premises Active Directory / Secr3t is an account in my work AAD that I use to log into
for a domain, an AAD is a list of logins that an app can vali- my work apps. And myeager@awesomeco.com / C0vert is a
Mike Yeager date against to see if someone is authorized to access the different account in my personal AAD that I use to log into
www.internet.com site or app. For the remainder of this article, just consider my personal Web page. The myeager@awesomeco.com ad-
the term AAD as being synonymous with a list of logins. dress also happens to be my company email address and my
Mike is the CEO of EPSs Houston company email server needs a different password to get my
office and a skilled .NET devel- Where do AADs come from? Every Azure account thats email. OK, I can live with that, but its getting complicated.
oper. Mike excels at evaluating created contains at least one AAD and perhaps more.
business requirements and
Thats a lot of AADs. Monkey wrench number three. Lets assume that my com-
turning them into results from
pany wants to get rid of our email server and switch to a
development teams. Hes been
If AAD only offered Work or school accounts, things would hosted Office 365 system. Microsoft has set up their own
the Project Lead on many
projects at EPS and promotes be simple. Each user account would follow the pattern user- AAD for Office 365. Office 365 authenticates against this
the use of modern best name@unique-add-name.xxx and each account would have AAD, owned by Microsoft. Microsoft recommends that we
practices, such as the Agile its own password. The user name and password would be sync our on-premises Windows domain Active Directory
development paradigm, use of created and exist in that AAD. For example, if I have an with this AAD in order to make the accounts easy to main-
design patterns, and test-drive Azure account where I work at Awesome Company, that tain. My email address myeager@awesomeco.com is now
and test-first development. Azure account would have a default AAD and that AAD might going to get pushed into Microsofts AAD for O365 and
Before coming to EPS, Mike was be configured with the unique-add-name of awesomeco.on- Im going to have to set up a password in that AAD. I set
a business owner developing a microsoft.com. I could then create a user name in the AAD the password to P@ssw0rd. Now I log into Office 365 to
high-profile software business like this: myeager@awesomeco.onmicrosoft.com and the get my email as myeager@awesomeco.com / P@ssw0rd.
in the leisure industry. He grew password might be Secr3t. Now Awesome Co can write and
the business from two employees publish Web, mobile, desktop, and other applications and
to over 30 before selling configure those apps to look at that AAD for authentication.
the company and looking for I could then log into one of those apps as myeager@aweso- The most important thing I
new challenges. Implementation meco.onmicrosoft.com / Secr3t. It would be simple.
experience includes .NET, SQL learned when logging into an
Server, Windows Azure, Microsoft So lets throw the first monkey wrench in the works. The
app and finding myself faced
Surface, and Visual FoxPro. unique-add-name.xxx gets created when an Azure ac- with the dreaded AAD login
count is set up. However If I own a domain name such screen is to look at things from
as AwesomeCo.com, I can associate that domain name the apps perspective, not my
with my AAD. Now, instead of myeager@awesomeco. own perspective as a user.
onmicrosoft.com, I can create the user name myeager@
awesomeco.com in the AAD. When I log in to one of the
apps, everything works just as it did before except that
I now use myeager@awesomeco.com / Secr3t to log in. Monkey wrench number four. I have a Microsoft ID that
What can make this confusing is that this may also hap- I set up years ago when it was still called Passport, way
pen to be my email address. Thats just a coincidence and before it was called Live ID. Its my personal Microsoft
one has nothing to do with the other. ID, not set up through my companys IT department, but
guess what my user name is? Its myeager@awesomeco.
Lets throw in monkey wrench number two. I might have com and my password is Ncript. When I created both my
a second Azure account, a personal Azure account. Its de- work and personal Azure accounts (and signed up for
fault AAD might have the unique-add-name mikeyeager. a few third party apps), I used my Microsoft ID. When
onmicrosoft.com. So there, I can create user accounts like I log into my work Azure account, my login is checked
myeager@mikeyeager.onmicrosoft.com with a password against one of Microsofts AADs. When I log into my per-
of C0vert. Now, suppose I associate my companys domain sonal Azure account, my login is checked against one of
with this AAD as well. I can create a user named myeager@ Microsofts AADs. When I log into the third-party apps,
In my last few articles, Ive explored a lot of JavaScript, jQuery, and the Web API. The code I wrote points out some deficiencies "colorName": "BLACK" "colorValue": "#4B0082",
when writing in these technologies. Thats the problem with JavaScript and jQuery: Its often difficult to write good, reusable, }, "colorName": "INDIGO"
and extensible code. However, things are changing fast in the client-side world, especially now that Angular and other similar { },
"colorValue": "#FF0000", {
"colorName": "RED" "colorValue": "#7FFF00",
frameworks have been invented. In the last article (CODE a variable called vm, which stands for View Model, and as- }, "colorName": "CHARTREUSE"
Magazine May/June 2016), you improved your client-side sign it to $scope. This saves you a little typing within your { },
code by using a closure and by using Mustache for data controller and may provide some flexibility later on, if you "colorValue": "#00FF00", {
binding. In this article, youll learn how these same con- ever want to change your service. The next snippet is the "colorName": "GREEN" "colorValue": "#FFA07A",
cepts are applied in Angular. IIFE youll create in another JavaScript file called product- }, "colorName": "LIGHT SALMON"
Controller.js. This file and the app.js file are both needed { }
"colorValue": "#0000FF", ]
The Web page youll build for this article is a search, list, on any HTML pages you intend to use with Angular.
add, edit and delete page of Product data for a fictitious
company called Pauls Training Company (PTC). All of the (function () {
Paul D. Sheriff features of this page are shown in Figure 1. In Figure 2, 'use strict';
you see just the search and list area displayed. In Figure Method Description
www.pdsa.com
3, only the detail area is displayed. Youll learn how to angular.module('ptcApp') CanActivate Implement to determine whether or not a view-model can be navigated to. Must return a Boolean value, promise for Boolean value,
Paul D. Sheriff is the President show and hide these various areas using Angular. .controller('PTCController', or navigation command.
of PDSA, Inc. PDSA develops PTCController); Activate Implement for custom logic needed before a view-model is displayed. When a promise is returned, the router waits for the promise to complete
custom business applica- before rendering the view.
tions specializing in Web and Create an Angular Application Scope function PTCController($scope) { CanDeactivate Implement to determine whether or not a view-model can be navigated away from.
mobile technologies. PDSA,
There are many articles and blog posts on what Angular is, var vm = $scope; Deactivate Implement for custom logic needed before navigation away from view-model. When a promise is returned, the router waits for the promise
founded in 1991, has success-
so I wont go into that here. The first thing you do in an to complete before navigating away.
fully delivered advanced custom
application software to a wide Angular application is create a module. For the sample in }
this article, create a file called app.js and place the follow- })(); Table 2: Aurelia Screen Activation Lifecycle
range of customers and diverse
industries. With a team of ing code in that file to create a module named ptcApp.
dedicated experts, PDSA delivers
cost-effective solutions, on-time (function () { Add Angular to Your Page constructor (httpClient) { cause a promise is being returned, the router waits until
and on-budget, using innovative 'use strict'; In order to understand the overall HTML structure that you this.httpClient = httpClient; the promise has completed before rendering the view. No-
tools and processes to better need for the product page, take a look at Listing 1. There } tice the use of a lambda expression in the then callback.
manage todays complex and angular.module('ptcApp', []); are two key pieces you need to have in order for Angular to This is more ES6 goodness from SystemJS.
competitive environment. Paul })(); control the elements on your page. The first is in the <html>
is also a Pluralsight author. elementthis is the ng-app directive. This directives value An ES2016 inject decorator is added to the top of the class Before running this code, add the data.json file to the root
Check out his videos at must be the same name as the application module name declaration, and a class constructor with a single parameter folder. Listing 8 shows its details. Once its added, refresh
http://www.pluralsight.com/ Create a Controller you used; in this article its called ptcApp. The second key is added after the class declaration. For every type injected the page to see a new list of colors that match the data file.
author/paul-sheriff. Once you have a module defined, create a controller into item is in the <body> element: the ng-controller directive. into the class, theres a matching constructor parameter.
which you place all the variables you need to use for bind- This directives value must be the same name as the con- Obviously, theres much more to HTTP communication
ing data to your HTML. The controller name used in this troller you defined; in this article, its called PTCController. Although this might be alien, its still JavaScript and not an than a simple GET in order to read a JSON file. The goal
article is called PTCController. Feel free to name this con- Aurelia construct. SystemJS makes it possible to write ES6 Ja- here is to demonstrate the base concept because all calls
troller whatever you want. Declare the controller within Note the use of bootstrap in the definition of the ele- vaScript and takes care of transcompiling to ES5 JavaScript. follow the same pattern: Make an asynchronous call to an
the scope of the module you created in the previous code ments of the page. Also notice the use of the comments HTTP endpoint, assign the data returned to one or more
snippet. Use the controller() function on the module to I put in to separate each area of the page. I find the use To use HttpClient, remove the headerColors and current- properties in the view-model, and bind to it in the view.
declare the name of your controller, as shown here: of comments helps me during debugging using the F12 Color properties from binding-demo.js and add the fol-
tools, and also helps me quickly identify areas when Im lowing method to the end of the class:
angular.module('ptcApp') looking at my HTML page in the editor. Conclusion and Going Further
.controller('PTCController', activate() { That should be enough to get you started. Our goal for this
PTCController); return this.httpClient.get('data.json') article was to introduce you to the Aurelia framework and
Handle UI State .then(data => { show you how simple and straightforward it is to begin us-
Pass in the name to use for the ng-controller directive Immediately after declaring your vm variable, start creat- this.headerColors = data.content; ing it to create your next JavaScript application. Weve been
and the function name that will enclose all of your vari- ing variables within your Angular scope by adding a new this.currentColor = using it on a current project and have found it to be a great
ables. The function declaration needs to accept a $scope property to your view model variable. For example, you this.headerColors[0]; addition to our development toolbox. Theres documentation
variable at a minimum. There are additional parameters might declare an object literal thats used to show or hide }); available on the Aurelia website (Aurelia.io), so go check it
that you may need to accept, depending on what services different areas of the HTML based on the current page } out. In the docs, youll find additional information about
you wish to use in your controller. Heres an example of mode or state. In Listing 2, you declare a new variable how Aurelia handles dependency injection, how to create
how to declare your controller function: named uiState. You then create a function to initialize Activate() is one of four optional methods in Aurelias custom attributes, how to secure your applications, how to
this variable with various properties that are used to con- Screen Activation Lifecycle. Table 2 documents all four of implement end-to-end testing, and much more.
function PTCController($scope) { trol your HTML, also shown in Listing 2. the optional methods.
var vm = $scope; Jim Duffy
} As your user interacts with your search, list, add, edit, Aurelias router enforces this lifecycle and provides hooks
and delete page, you need to display different parts of the to view-models to control flow in to and out of compo-
One best practice is to immediately create a variable that page based on the current mode. In the uiState variable, nents. The activate method makes an HTTP call to get the Jeremy Brown
can be used instead of typing $scope over and over. Create you create a property called mode thats set to one of data.json file and returns a promise to the router. Be-
Aurelia: An Introduction Listing 8: Gather data from the Angular error object to display to the user
function handleException(error) {
// Get error information
var msg = {
}
+ error.data.ExceptionMessage;
Aurelia is an open-source UI JavaScript framework designed to create single page applications (SPAs) that doesnt behave like property: error.status, // Reset array & add error message
a framework. Its been built from the ground up using modern tooling and ECMAScript 2016 with full support for TypeScript. message: error.statusText vm.uiState.messages = [];
Its architecture is a series of collaborating libraries and WebComponents woven together with plain modern JavaScript. }; vm.uiState.messages.push(msg);
// Add any additional error text to message // Set UI State to Exception or Validation
Aurelia is designed to help you create applications for the to use your GitHub credentials or personal access token. if (error.data != null) { setUIState(pageMode.EXCEPTION);
browser, mobile devices, or the desktop. Type the following from a command prompt, and then fol- msg.message += ' - ' }
low the prompts to register your GitHub account with jspm:
The Aurelia website (Aurelia.io) documents all the benefits
it provides, so well only mention a few that we really like. jspm registry config github
Aurelia adheres to a convention over configuration phi- function (error) { Listing 9: Create an HTML table using Angular data binding and ng-repeat directive
losophy that helps developers follow established patterns Next, consider how the app is going to run locally. There handleException(error); <tbody>
by reducing the amount of code required to build an ap- are three options. }); <tr ng-repeat="product in products">
plication. Its easy to learn but that doesnt mean it lacks } <td class='pdsa-action-button-column'>
Jim Duffy robustness or power. Developers only need to learn a small The first option uses a simple NodeJS Web server. The fol- <a href='#' class='btn btn-default btn-sm'
jduffy@takenote.com set of patterns before they can begin making significant lowing command installs an http server globally: Locate the call to the init() function at the top of your ng-click="editClick(product.ProductId)">
Twitter: @jmduffy progress on their own application. Aurelia has been de- controller function and add a call to the getAll() func- <i class='glyphicon glyphicon-edit'></i>
Jim Duffy is founder and CEO signed to be extensible, which makes it an ideal choice for npm install http-server -g tion after the init() call. Calling this function after the </a>
of TakeNote Technologies, working with third-party libraries and frameworks. Aurelia init() function causes the product page to display a list of </td>
is backed by Durandal Inc., which was established to pro- Theres nothing to serve at the moment. Well spin up the products right when the page is loaded. If you dont want <td>{{product.ProductName}}</td>
an award-winning training,
vide commercial and enterprise Aurelia support resources, <td>{{product.IntroductionDate | date: 'MM/dd/yyyy'}}</td>
consulting, and develop- server later. products displayed upon entry, dont call this function.
<td>{{product.Url}}</td>
ment company specializing in assuring customers that help is there if they need it.
<td>{{product.Price | currency: "$"}}</td>
.NET developer training with The second option uses Visual Studio and opens the proj- // Get all products
<td class='pdsa-action-button-column'>
Microsoft enterprise, Azure, and ect as a Website. From Visual Studios menu, select File getAll(); <a href='#' class='btn btn-default btn-sm'
open-source technologies. > Open > Open Website. Navigate to the projects folder
Hes a Microsoft Regional
Aurelia adheres to a convention- ng-click="deleteClick(product.ProductId)">
and click Open. <i class='glyphicon glyphicon-trash'></i>
Director, 11-time Microsoft over-configuration philosophy
</a>
MVP, an ASPInsider, and an that helps developers follow The third option uses Firefox. Firefox allows serving the As Angular iterates through </td>
Azure Insider, as well as a established patterns and helps app directly from your hard drive. the array, it uses the property </tr>
popular speaker at international them reduce the amount of </tbody>
developer conferences. name on the product object to
code required to build their With the tooling in place, you can start your first Aurelia build your HTML table.
applications. app from scratch.
ence the products array to get each product one-by-one and
build a <tr> element for each, as shown in Listing 9. SPONSORED SIDEBAR:
Hello Aurelia! Handle Exceptions
Modern Tooling Create an empty folder called HelloAureila and open a If an HTTP status code that doesnt lie between 200 and The code in Listing 9 uses the data binding syntax like
Web Mentoring
Aurelia is built from the ground up using modern tool- command prompt to that location. Initialize jspm using 299 is returned, the code in the error function is executed. you used for displaying messages earlier in this article. Looking for the perfect
ing. It uses Node.js and is designed to work with pack- the following command: In the case of an exception, display an error message to The ng-repeat directive creates a product object for each support package for
age mangers like jspm (JavaScript Package Manager) for the user. Create a handleException() function, as shown object contained in the products array. As Angular iter- your Web application?
dynamic module loading and transcompiling ECMAScript jspm init in Listing 8. ates through the array, it uses the property name on the CODE Consultings special
Jeremy Brown 6 (ES6) code to ECMAScript 5 (ES5). Aurelia applications product object to build your HTML table. introductory offer gives
can be written the same way, but it isnt a requirement. Follow the series of questions to set up jspm and press The error object returned from the $http data service is an you full access to a CODE
jeremy@jeremysbrown.com
Twitter: @jeremysbrown Theres support for using TypeScript and Webpack as an Enter for each question to accept the defaults. Use the object with a few properties that are of interest. The status When you use the ng-click directive in the edit and delete team member for 20 hours
alternative. Getting a project set up is perhaps the most following two commands after jspm has initialized to load property is the HTTP status code returned from the Web API anchor tags, you dont need to use the double curly braces to receive assistance
Jeremy Brown is a software laborious part, but the Aurelia team is working on a CLI the base Aurelia framework and its bootstrapping library: call. This might be something like 500, 404, or any other as you do with normal data-binding in Angular. Because with mentoring and project
consultant and speaker with so that future set ups will be much easier. error code. The statusText is the typical text, like internal youre using an Angular directive, it already knows that roadblocks.
over 20 years of experience. jspm install aurelia-framework server error or resource not found. If your Web API gen- any object you pass within the directive is contained Email info@codemag.com
He has been developing for This article goes the traditional route and uses jspm with jspm install aurelia-bootstrapper erates any additional error text, you can retrieve that from within the scope of the controller. to set up your time with a
the Web since 1995 and with CODE specialist, today!
SystemJS. If you dont have NodeJS installed, download it the data objects ExceptionMessage property.
the .NET Framework since
from http://node.org. The remaining tooling is installed Open the config.js using your favorite IDE, and add the
2002. His passion for writing
using Nodes package manager npm, including jspm. following two strings to babelOptions (about line 5): Once you have the error information, create an object that Summary
software began the very first
moment his Commodore has property and message properties. Store the informa- In this article, you started your journey to learning to use
Vic-20 connected to his Once you have NodeJS installed, open a command prompt "es7.decorators", tion you want to display to the user in the message prop- Angular to create a simple add, edit, and delete page. You
familys television set. and type the following to install jspm: "es7.classProperties" erty. Push this object onto your uiState.messages array also learned how to control visibility of different areas on
and call the setUIState() function, passing in the Excep- a single page. You then learned how to display validation
npm install g jspm You should have the following: tion mode, and this makes the message area visible on the and error messages. You finished by making a Web API
screen with the error text displayed. call to retrieve product data. In the next article, youll
GIT must be installed because jspm has a dependency on GIT learn how to retrieve a single product and how to insert,
to query GitHub for packages. Download GIT from https:// babelOptions: { Build an HTML Table Using Angular Templates update, and delete data using Angular and the Web API.
git-scm.com. We also recommend creating a GitHub ac- "optional": [ Build a template within the <tbody> tag to bind the product
count if you dont already have one. GitHub has a rate limit "runtime", data to the table. Use the ng-repeat directive as you did Paul D. Sheriff
for anonymous API requests, so its best to configure jspm "optimisation.modules.system", when building the message list. For the product table, refer-
When its fresh and new, were excited about the 1. It redirects you to the AzureAD authentication end
possibilities and capabilities. point with enough information in the querystring pa-
When its fresh and new, we miss all the support rameters allowing AzureAD to identify your application,
and libraries and knowledgebase that has yet to be and a redirect URI, i.e., where to send the ID_TOKEN
created for it. back once the authentication has been performed.
2. Once your application receives an ID_TOKEN, it does
Speaking of libraries and knowledgebases, for Angular- another GET request, asking for an access token for
JS1, we had Ionic, we had Electron, and we had some specific resources. In other words, ID_TOKEN iden-
pretty sweet TDD frameworks. I hope to cover their re- tifies you as the user, but then to get an access
NameMalik
Sahil Autor placements in future articles. In this article, Ill talk token that lets you call Microsoft Graph, you have
www.winsmarts.com
www.internet.com about an empty hole that most Microsoft developers will to request an access token specific to the Microsoft
@sahilmalik notice, and that is ADAL.js. Graph, etc.
asdfasdfasdfasdfker, a .NET
Sahil
author,Malik is a Microsoft
consultant MVP,
and trainer. This two step process, while necessary for AzureAD, Com-
INETA speaker, a .NET author, ADAL.js mon Consent, and Office 365, is arguably both more
Sahilasfasdfasdfasdfasdfasdfd-
consultant, and trainer.
fainings are full of humor and ADAL.js is the JavaScript active directory authentication powerful and more complex than simple OAuth. I use the
Sahil loves
practical interacting
nuggets. withfind
You can fel- library. Although it could be used outside of AngularJS, word complex with some reservations thoughtwo GET
low
moregeeks
aboutinhis
realtrainings
time. Hisattalks it was written with AngularJS1 in mind. It worked on a requests is hardly complex, but you get my drift.
and trainings are full of humor
http://wwasdfasdfasfasdfasdf concept of pushing in HTTP Interceptors that examined
and practical nuggets. You can every request going out and coming in. Every request go- In order to create an application structure, Ive encapsu-
find more about his training at ing out was automatically modified by adding an access lated all this logic into its own Angular2 service. If you
http://www.winsmarts.com/ token. Every request coming in automatically checked for wish to replace it with simple OAuth, you just need a dif-
training.aspx. a 401 (Unauthorized) HTTP status code, and asked the ferent, albeit simpler, implementation of this service. The
user to perform the Azure AD authentication. ADAL.js also rest of the concepts demonstrated here will work with
His areas of expertise are cross- renewed access tokens using a hidden IFrame, and had simple OAuth also.
platform mobile app develop- enough smarts to understand the limitations of various
ment, Microsoft anything, and browsers and provide suitable workarounds.
security and identity.
ADAL.js could be improved however.
Wrapping Up
Using the techniques presented in this article and con-
sulting the accompanying source code download, you can
develop your own fully customized language using your
own keywords and functions. The resulting language will
be interpreted at runtime directly, statement by statement.
ParserFunction.AddGlobal(Constants.ROUND,
new RoundFunction());
AddTranslation(languageSection, Constants.ROUND);
62 How to Write Your Own Programming Language in C# codemag.com codemag.com Title article 15
What Will I Build gular2 app thats almost exactly like the quick starter you
can find at angular.io.
Listing 6: Get directory or file info on Unix and on Windows
In this article, Im going to build a simple application. It public static string GetPathDetails(FileSystemInfo fs, string name)
will use AngularJS2; specifically, itll make use of Routing, { if (info.IsSymbolicLink) {
Now lets start building the actual application logic. What
HTTP, and demonstrate how you can call APIs protected string pathname = fs.FullName; d = 's';
I intend to do is:
by AzureAD using AngularJS2. Ill also show how I struc- bool isDir = (fs.Attributes & FileAttributes.Directory) != 0; }
tured the application, the naming conventions I used, etc. Set up basic routing between two main routes:
Theres a lot of detail to cover here; Ill keep this article char d = isDir ? 'd' : '-'; #else
files and login. The intention is that the starter
pertinent to AngularJS2, and refer you to ancillary con- string last = fs.LastAccessTime.ToString("MMM dd yyyy HH:mm"); string user = string.Empty;
page consists of files, and it prompts the user to string group = string.Empty;
cepts, such as registering applications in AzureAD, or the click a button, which, behind the scenes, executes
specific authentication flow to use (and more) to alternate #if __MonoCS__ string links = null;
a command to query for files in the Microsoft Mono.Unix.UnixFileSystemInfo info; string permissions = "rwx";
resources on the Internet. Also, Ill share source code. Graph. And if the user isnt logged in, it redirects if (isDir) {
the user to the login route, where the user clicks info = new Mono.Unix.UnixDirectoryInfo(pathname); long size = 0;
Here are the references youll need to follow along with a button to perform AzureAD authentication and } else {
this article. gain an access token. The goal here is that the info = new Mono.Unix.UnixFileInfo(pathname); if (isDir)
author of the application logic shouldnt have to } {
Azure Active Directory basics: http://www.codemag. worry about the cruft of authentication. I should user = Directory.GetAccessControl(fs.FullName).GetOwner(
com/Article/1503041 be able to call the REST APIs, authenticationno char ur = (info.FileAccessPermissions & typeof(System.Security.Principal.NTAccount)).ToString();
Extending Office365: http://www.codemag.com/ matter what kind it isand should be transparent Mono.Unix.FileAccessPermissions.UserRead) != 0 ? 'r' : '-';
Article/1507031 to the application logic. char uw = (info.FileAccessPermissions & DirectoryInfo di = fs as DirectoryInfo;
Source code for this article: https://github.com/ Create a service to help with AzureAD authentication. Mono.Unix.FileAccessPermissions.UserWrite) != 0 ? 'w' : '-'; size = di.GetFileSystemInfos().Length;
maliksahil/Angular2AzureAD Create another service to encapsulate all my HTTP char ux = (info.FileAccessPermissions & }
calls that I wish to be authenticated. Mono.Unix.FileAccessPermissions.UserExecute) != 0 ? 'x' : '-'; else {
Create a file to hold some constants that Ill need char gr = (info.FileAccessPermissions & user = File.GetAccessControl(fs.FullName).GetOwner(
Basic Application Structure for the AzureAD app identification, etc. Mono.Unix.FileAccessPermissions.GroupRead) != 0 ? 'r' : '-'; typeof(System.Security.Principal.NTAccount)).ToString();
This application is built using AngularJS2 and TypeScript. char gw = (info.FileAccessPermissions & FileInfo fi = fs as FileInfo;
My dev environment is VSCode. To start cloning this git, Lets get started. For the routing, youll need the central Mono.Unix.FileAccessPermissions.GroupWrite) != 0 ? 'w' : '-'; size = fi.Length;
repo https://github.com/maliksahil/Angular2Start. This app.component.ts, so go ahead and create a file with that char gx = (info.FileAccessPermissions &
gives you a basic Angular2 app using TypeScript. You can name under the app folder. Mono.Unix.FileAccessPermissions.GroupExecute) != 0 ? 'x' : '-'; string[] execs = new string[] { "exe", "bat", "msi"};
open that directory in VSCode, and run npm install and char or = (info.FileAccessPermissions & char x = execs.Contains(fi.Extension.ToLower()) ?
npm start to get started. If youre curious, feel free to Youll need two pages, login and files. Go ahead and cre- Mono.Unix.FileAccessPermissions.OtherRead) != 0 ? 'r' : '-'; 'x' : '-';
see how that app is constructed; its a plain vanilla An- ate a login.component.ts and login.component.html. char ow = (info.FileAccessPermissions & char w = !fi.IsReadOnly ? 'w' : '-';
Mono.Unix.FileAccessPermissions.OtherWrite) != 0 ? 'w' : '-'; permissions = string.Format("r{0}{1}", w, x);
char ox = (info.FileAccessPermissions & }
Mono.Unix.FileAccessPermissions.OtherExecute) != 0 ? 'x' : '-';
#endif
string permissions = string.Format("{0}{1}{2}{3}{4}{5}{6}{7}{8}",
ur, uw, ux, gr, gw, gx, or, ow, ox); string infoStr = string.Format(
"{0}{1} {2,4} {3,8} {4,8} {5,9} {6,23} {7}",
string user = info.OwnerUser.UserName; d, permissions, links, user, group, size, last, name);
string group = info.OwnerGroup.GroupName;
string links = info.LinkCount.ToString(); return infoStr;
}
long size = info.Length;
In the code snippet above, you see Unix-specific code to Figure 3 shows running the ls command on a Mac and
get the directory or file data structure. Using this struc- Figure 4 shows running a dir command on a PC.
ture, its easy to find typical Unix permissions for user/
group/others, which dont make sense on Windows: The question that might strike you now is: How do I con-
figure using the ls command on a Mac and the dir com-
char ur = (info.FileAccessPermissions & Mono.Unix. mand on a PC for the same CSCS function?
FileAccessPermissions.UserRead) != 0 ? 'r' : '-';
char uw = (info.FileAccessPermissions & Mono.Unix.
FileAccessPermissions.UserWrite) != 0 ? 'w' : '-'; Keywords in Different Languages
char ux = (info.FileAccessPermissions & Mono.Unix. If you want a keyword to be used in any other language, you
FileAccessPermissions.UserExecute) != 0 ? 'x' : '-'; must add a code so that you can read possible translations
char gr = (info.FileAccessPermissions & Mono.Unix. from the configuration file. For example, I defined the keyword
FileAccessPermissions.GroupRead) != 0 ? 'r' : '-'; for a function to show the contents of a directory as follows:
...
string permissions = string.Format( public const string DIR = "dir";
"{0}{1}{2}{3}{4}{5}{6}{7}{8}",
ur, uw, ux, gr, gw, gx, or, ow, ox); Now, if I want possible translations of this keyword I add
in the Interpreter initialization code:
Take a look at Listing 6 for the complete implementation
Figure 2: The native client app permissions of the GetPathDetails() function. AddTranslation(languageSection, Constants.DIR);
16 AngularJS2, AzureAD, and Office365 codemag.com codemag.com How to Write Your Own Programming Language in C# 61
Similarly, create a files.component.ts and a files.compo-
nent.html. Note the naming convention Im following; by
Writing the Services
looking at the filename, its pretty clear what each file Next, lets focus on the services. The first service is the
does. Also, its a lot easier to search for files in Visual AzureADAuthHelper.ts file. The logic here is quite easy.
Studio code if they are named intuitively. It exposes a public method called login that starts the
entire login process. The login logic works as follows:
Next, lets add files for the services. Add a file called
azureADAuthHelper.service.ts, which is the service that Listing 1: The serviceConstants.ts file
helps you encapsulate AzureAD authentication. Add
another file called authenticatedHttp.service.ts, which export class SvcConsts {
encapsulates all HTTP calls that I wish to be authenti- public static CLIENT_ID: string =
"5c74c564-8ea2-477d-acdd-09618455bd1d";
cated.
public static TENTANT_ID: string =
"winsmartsdev.onmicrosoft.com";
Finally, add a file called serviceConstants.ts. This holds public static GRAPH_RESOURCE: string =
Figure 3: Running CSCS ls command on a Mac the various constants you need to identify the application "https://graph.microsoft.com";
with AzureAD. }
dio project from Windows. What I did have to change is www.codemag.com/consulting 15 http://ravendb.net 5
shutterstock.com/McIek/dotshock
"System.Configuration.NameValueSectionHandler"/> string name) CODE Magazine Tower 48
<section name="Synonyms" type= { www.codemag.com/magazine 63 www.tower48.com 75
Writing Your Own Programming Language
"System.Configuration.NameValueSectionHandler"/> string pathname = fs.FullName; CODE Staffing Xamalot An Intro to the Internet of Things
60 How to Write Your Own Programming Language in C# codemag.com codemag.com AngularJS2, AzureAD, and Office365 17
Listing 3: login.component.ts Listing 5: Implementation of the ++ and -- operators
import { Component } from "angular2/core"; protected override Variable Evaluate(string data, if (arrayIndex >= 0)
import { AzureADAuthHelper } from "./AzureADAuthHelper.service"; export class LoginComponent { ref int from) {// A variable with an index (array element).
constructor(private _azureADAuthHelper:AzureADAuthHelper) {} { if (currentValue.Tuple == null)
@Component({ login() { bool prefix = string.IsNullOrWhiteSpace(m_name); {
selector: "login", this._azureADAuthHelper.login(); if (prefix) throw new ArgumentException("Tuple [" + m_name +
templateUrl: "app/login.component.html", } {// If it's a prefix we do not have variable name yet. "] doesn't exist");
providers:[AzureADAuthHelper] } m_name = Utils.GetToken(data, ref from, }
}) Constants.TOKEN_SEPARATION); if (currentValue.Tuple.Count <= arrayIndex)
} {
throw new ArgumentException("Tuple [" + m_name +
// Value to be added to the variable: "] has only " + currentValue.Tuple.Count + " elements");
Listing 4: files.component.ts int valueDelta = m_action == Constants.INCREMENT ? 1 : -1; }
int returnDelta = prefix ? valueDelta : 0; newValue = currentValue.Tuple[arrayIndex].Value + returnDelta;
import { Component } from 'angular2/core';
currentValue.Tuple[arrayIndex].Value += valueDelta;
import { HTTP_PROVIDERS } from 'angular2/http'; export class FilesComponent {
// Check if the variable to be set has the form of x(0), }
import { AuthenticatedHttpService } private files = []; // meaning that this is an array element. else // A normal variable.
from './authenticatedHttp.service'; constructor( double newValue = 0; {
import { AzureADAuthHelper } from "./AzureADAuthHelper.service" private _http: AuthenticatedHttpService) { } int arrayIndex = Utils.ExtractArrayElement(ref m_name); newValue = currentValue.Value + returnDelta;
bool exists = ParserFunction.FunctionExists(m_name); currentValue.Value += valueDelta;
@Component({ getFiles() { if (!exists) }
selector: "files", var resourceURL = "https://graph.microsoft.com/v1.0/me/ {
templateUrl: "app/files.component.html", drive/root/children"; throw new ArgumentException("Variable [" + m_name + Variable varValue = new Variable(newValue);
providers: [ this._http.get(resourceURL).then((files) => { "] doesn't exist"); ParserFunction.AddGlobalOrLocalVariable(m_name,
HTTP_PROVIDERS, this.files = files.value; } new GetVarFunction(currentValue));
AuthenticatedHttpService, }) return varValue;
AzureADAuthHelper] } Variable currentValue = ParserFunction.GetFunction(m_name) }
}) } GetValue(data, ref from);
action functions is analogous. As you can see, the Parser The function size() is implemented as a typical CSCS func-
It redirects you to the AzureAD sign-in page with Client ID, TenantID, and requesting permission knows from the context whether it works with a prefix or tion returning the number of elements in an array. But if
some information that includes the ClientID and Re- on a specific resource. Assuming that the app has a postfix operator and if it was triggered because of a -- the passed argument isnt an array, it returns the number
directURI. Client ID is the identity you put in the that access granted, which you set up in Figure 2, or a ++ action. Note that at the end, the function returns of characters in it.
serviceConstants.ts file and RedirectURI is where youre returned an access token. This access to- either the current variable value (in case of the prefix) or
you wish the ID Token to be sent back to, which, in ken is then available as a public property on this the previous value in case of the postfix. Internally, an array is implemented as a C# list so you can
this case, is the app itself. object. add elements to it on the fly.
Once you get the ID Token, do another redirect to With this approach, you can play around with the assign-
the AzureAD token endpoint with this ID token, You can find the entire code in the associated code down- ments in CSCS as follows: You access elements of an array, or modify them, by using
load at https://github.com/maliksahil/Angular2AzureAD, the squared brackets. If you access an element of an array
but really, its the above logic you need to know. The code, a = 1; and that element has not been initialized yet, an excep-
Listing 5: The databound view which is quite wordy, does the above described logic. b = a++ - a--; // b = -1, a = 1 tion will be thrown by the Parser. However, its possible to
<button (click)="getFiles()">Get Files</button> c = a = (b += 1); // a = b = c = 0 assign a value to just one element of an array, even if the
<ul> Once youve written the AzureADAuthHelper.ts, focus on a -= ++c; // c = 1, a = -1 index used is greater than the number of elements in the
<li *ngFor="#file of files"> the authenticatedHttp.service.ts service. The intention of c = --a - ++a; // a = -1, c = -1 array. In this case, non-existing elements of the array are
<span>{{file.name}}</span> this service is to act as an authenticated HTTP client. Its initialized with empty values. This happens even if its the
<span>{{file.size}}</span> a class thats injectable, and it inherits from the normal The Listing 5 has a section about arrays. I havent talked first assignment for this array. For this special shortcut
</li> HTTP client. This AuthenticatedHttpService, accepts the about them yet. How do the assignments work with arrays? array assignment, the CSCS function set() is used:
</ul> azureADAuthHelper class as an injected dependency. The
reason that Ive structured the code in this form is be- i = 10;while(--i > 0) {
cause now I can inject any other kind of authentication Arrays newarray[i] = 2*i;
The declaration of an array is different from the declara- }
tion of a variable in CSCS. To declare an array and ini-
Listing 6: The app.component.ts defining the overall routes tialize it with data, you use the same statement. As an print("newarray[9]=", newarray[9]); // 18
import { Component } from 'angular2/core'; }) example, heres the CSCS code: print("size(newarray)=", size(newarray)); // 10
import { Router, RouteConfig,
ROUTER_DIRECTIVES, ROUTER_PROVIDERS} @RouteConfig([ a = 20; Check out the array implementation in the accompany-
from "angular2/router"; { path: '/files', name: 'Files', component: FilesComponent }, arr = {++a-a--, ++a*exp(0)/a--, ing source code download (available through the CODE
import {LoginComponent} from './login.component'; { path: '/login', name: 'Login', component: LoginComponent } -2*(--a - ++a), ++a};i = 0; Magazine website).
import {FilesComponent} from './files.component'; ]) while(i < size(arr)) {
print("a[", i, "]=", arr[i],
@Component({ export class AppComponent { ", expecting ", i);
Compiling on Various Operating
selector: 'app', constructor(private _router: Router) { i++; Systems
template: '<router-outlet></router-outlet>', this._router.navigate(['/Files']); } Its a common misunderstanding that C# is for Windows
directives: [ROUTER_DIRECTIVES], } only. People may have heard of a few attempts to port it
providers: [ROUTER_PROVIDERS] } The number of elements in the array isnt explicitly de- to other operating systems, but most think that those at-
clared because it can be deduced from the assignment. tempts are still in some kind of a work in progress.
18 Title article codemag.com codemag.com How to Write Your Own Programming Language in C# 59
tions, like you used with Round() or try/throw control print (i, " is odd."); helper, for instance, an ADFS 3.0 OAuth authentication As my application grows, I just need to tell my team that
statements. The include keyword is also defined in Con- } helper. they should use the AuthenticatedHttpService client in-
stants.cs: } stead of the normal HTTP client. And since the API is pro-
The AuthenticatedHttpService has a constructor that ac- tected by authentication anyway, I think therell be no
public const string INCLUDE = "include"; Try to guess: In the CSCS code above, how many of the cepts the following dependencies: danger of someone not using the unauthenticated client;
tokens are implemented as functions (that is, classes it simply wont work. Plus, if I ever wish to use a different
The function implementation is in the IncludeFile class deriving from the ParserFunction class)? There are four: HTTP (from angular2/http) authentication provider, the change is encapsulated in a
deriving from the ParserFunction class: while(), if (), print(), and ++. Else isnt a function by Router (from angular2/router) single file.
itself, its processed together with if (similarly, catch AzureADAuthHelper (from azureADAuthHelper.ts)
ParserFunction.AddGlobal(Constants.INCLUDE, is not a separate function but is processed together
new IncludeFile()); with try). You might be wondering, why Im injecting the router. The idea
is that this authenticatedHttpService client wraps the normal,
In the CSCS code, including another file looks like this: What about the i++ token inside of the while() statement? out-of-the-box HTTP object; if your call results in a 401 error
How is it implemented? (unauthorized), it automatically redirects to the /Login route.
include("filename.cscs"); This means that the rest of the application need not do all
Implementing ++ and -- Prefix and these checks; I have them neatly tied up in a single class.
As soon as the Parser gets the INCLUDE token (or one of
its translations), the execution of IncludeFile.Evaluate()
Postfix and Compound Assignment Next, I need to implement the various GET, POST, DELETE,
is triggered. This function must first extract the actual Operators PUT methods that implement this behavior. For the sake
script from the file to be included: You can use the same approach for assignment as you did of brevity, Im only demonstrating a simple GET call, but
for including a file by implementing it as a function set(), you can implement other methods, as necessary. The logic
class IncludeFile : ParserFunction for example. This is how I implemented the assignment for the GET method can be seen in Listing 2.
{ in the first version of the language described in MSDN
protected override Variable Evaluate( Magazine (See the sidebar for a link). As can be seen in Listing 2, if the return happens to be
string data, ref int from) an error, and the error happens to be a 401 (unauthor-
{ The assignment a = 5 is equivalent to set(a, 5), the prefix ized), Im simply routing to the Login page.
Figure 3: Application launch
string filename = Utils.ResultToString( operator ++i is equivalent to set(i, i + 1). The postfix
Utils.GetItem(data, ref from)); operator i++ is a bit longer: i++ is equivalent to set(i, i +
string[] lines = Utils.GetFileLines(filename); 1) 1 in CSCS. The Login Component
string includeFile = string.Join( The login component now becomes incredibly simple!
Environment.NewLine, lines); A language with such awkward assignment operators Really, all it needs to do is offer a sign in button that
string includeScript = cant, obviously, be part of the Premier League of pro- calls AzureADAuthHelper.login(). The TypeScript portion
Utils.ConvertToScript(includeFile); gramming languages. You need a different approach to of this component can be seen in Listing 3.
have proper assignment operations.
Then you process the whole script using the Parser main Also, the HTML for this component in the login.compo-
method, LoadAndCalculate(). Note that at the end, you nent.html file can be seen in this snippet:
return an empty result because theres nothing to return
upon completion. To be part of the Premier <button (click)="login()">Sign-in</button>
League of Programming
int filePtr = 0; Languages, you need As can be seen, its just a simple button that calls Azure
while (filePtr < includeScript.Length) to have proper operator ADAuthHelperwhich is injected into the constructor as
{
assignment. a dependency.
Parser.LoadAndCalculate(includeScript,
ref filePtr, Constants.END_LINE_ARRAY);
Utils.GoToNextStatement(includeScript, The Functionality (Files) Component Figure 4: Login component
ref filePtr); I decided to take the following approach: Declare action Now here is where you can begin to reap the benefits of
} functions, all deriving from the abstract ActionFunction the application structure. The code for the TypeScript com-
return Variable.EmptyInstance; class (that derives from the ParserFunction class). An ac- ponent of the Files component can be seen in Listing 4.
} tion function is triggered as soon as the Parser gets any
} of the following action tokens: ++, --, +=, -=, *=, etc. In
case of ++ and --, you need first to find whether its a
All of the global functions added from the included file prefix or a postfix operatorthe Parser will know that: In Instead of using the usual
stay with the Parser after completion of the Include state- case of a prefix, it will have an unprocessed token before out-of-the-box HTTP client
ment. the action. to make the rest call,
youre using the HTTP client.
You can implement if, when, for, and other control flow All of the actions must be registered with the Parser first:
statements in the same way you implemented the includ-
ing of a file. I havent implemented the for loop because ParserFunction.AddAction(Constants.ASSIGNMENT,
its functionality can be easily achieved with a while loop. new AssignFunction()); As is evident, youre injecting the authentication services.
Heres an example of such a substitution of the for loop ParserFunction.AddAction(Constants.INCREMENT, Then, instead of using the usual outof--the-box HTTP cli-
in the CSCS code: new IncrementDecrementFunction()); ent to make the REST call, youre using the HTTP client
ParserFunction.AddAction(Constants.DECREMENT, to make the call. Yep, its really as simple as that now.
i = 0;while (i++ < 10) { new IncrementDecrementFunction()); Whats happening behind the scenes is that the services
if (i % 2 == 0) { are encapsulating the redirect to login, etc., the junk that
print (i, " is even."); Check out the implementation of the IncrementDecre- honestly, Id rather not have to worry about when Im
} else { mentFunction() in Listing 5. The implementation of other writing the actual business logic. Figure 5: The application running
58 How to Write Your Own Programming Language in C# codemag.com codemag.com Title article 19
As you can guess, if the call succeeds, Im setting the files fast, you might miss them, or just run your code in debug from++; // skip opening parenthesis } catch(exc) {
property on my exported class, which Im simply data- mode and set breakpoints. print ("Caught Exception: ", exc);
binding to the view, as can be seen in Listing 5. // The next token after the try must be a catch. }
After those directs, youll have an access token, and if (!Constants.CATCH_LIST.Contains(catchToken))
youll be back on the files component, similar to Figure { After running it, you get the following exception mes-
The Main App and Routing 3. Because you have a valid access token now, clicking throw new ArgumentException( sage:
All thats left to do now is set up the overall app routing on Get Files now queries your OneDrive for the files you "Expecting a 'catch()' but got [" +
and bootstrap code. might have there, as shown in Figure 5. catchToken + "]"); Trying to calculate negative factorial...
} Caught Exception: Negative number (n=-5)
The bootstrap code can be seen here: Thats all there is to it. You just wrote a simple Angu- for factorial at
larJS2 application thats able to query OneDrive. You string exceptionName = Utils.GetNextToken(data, factorial()
import {bootstrap} could easily enhance this to add more functionality if ref from); tryNegative()
from 'angular2/platform/browser'; you wish. from++; // skip closing parenthesis trySuite()
import {AppComponent}
from './app.component' Why do you use a CATCH_LIST to see if the catch keyword Of course, this is a bare bones exception handling so you
import { Summary is there and not just Constants.CATCH = catch? Because might want to add some fancier stuff, like at what line of
Router, RouteConfig, This article showed you a practical implementation of how the CATCH_LIST contains all possible translations of the the function the exception was thrown, function param-
ROUTER_DIRECTIVES, you can write AngularJS2 single page applications that catch keyword in different languages. You provide them in eters, and so on.
ROUTER_PROVIDERS authenticate with AzureAD, and are able to call AzureAD the configuration file. For example, you can use atrapar
} from "angular2/router"; protected APIs, such as Microsoft Graph. In the process of in Spanish, or fangen in German..
SPONSORED SIDEBAR: bootstrap(AppComponent, [ROUTER_PROVIDERS]); writing this app, I was able to demonstrate how I com-
posed my application, how I structured and named the In case of an exception, you must process the catch block. You can add fancy stuff,
Need Help? Its the usual Angular2 bootstrap code that youd ex- files. I also showed how I made use of dependency injec- You first create an exception stack (what was called from including which line
pect. Im injecting router-related directives and provid- tion, a key feature of AngularJS, to encapsulate all of my what) and then add this information to the exception of the function threw
Looking to convert your ers because I intend to use them all over the applica- authentication logic in a single place, making the rest of variable that can be used in the CSCS code that caught the exception.
application to a new tion. You could inject the authentication helper class my application neat and clean. the expression:
language, or need help here as well.
optimizing your application? This is by far not production-ready code. Ideally, Id want if (exception != null) {
The experts at CODE Consulting The app.component.ts, which is your bootstrapped com- to enhance the authentication helper classes to allow me string excStack = CreateExceptionStack( How do you keep track of the execution stack? That is, of
are here to help with your ponent, simply needs to define the routing now. This can to store the ID token for long-running applications. Or currentStackLevel); the functions being called? In ParserFunctions, you define
project needs! From desktop be seen in Listing 6. As can be seen, youre defining two be able to support multiple authentication providers. Or ParserFunction.InvalidateStacksAfterLevel( the following static variable:
to mobile applications, CODE routes: one for login and one for the application itself. As perhaps the ability to package this app into a mobile app currentStackLevel);
developers have a plethora
the app grows more complex, you can define more routes using Cordova, or desktop apps using Electron. That and GetVarFunction excFunc = new GetVarFunction( public class StackLevel
of experience in developing
here, or define child routes in underlying components. more will be covered in subsequent articles. new Variable(Double.NaN, {
software and programs
As long as you continue to use the Authentication helper exception.Message + excStack)); public StackLevel(string name = null) {
for different platforms.
For more information visit services, it should all still work. In the meanwhile, happy coding! ParserFunction.AddGlobalOrLocalVariable( Name = name;
www.codemag.com/consulting exceptionName, excFunc); Variables = new Dictionary<string,
Sahil Malik ParserFunction> ();
or email us at info@codemag.com. Running the Application result = ProcessBlock(data, ref from); }
From the terminal or command prompt, run npm start ParserFunction.PopLocalVariable( public string Name { get; set; }
to launch the application and typescript compilation. The exceptionName); public Dictionary<string, ParserFunction> Variables
browser should launch pointing to http://localhost:3000. } { get; set; }
Ensure that http://localhost:3000/* is specified as a }
wildcard redirect URI in your AzureAD app registration. In case theres no exception, skip the catch block: private static Stack<StackLevel> s_locals =
The application should load at the /files URL because that new Stack<StackLevel>();
is defined as the first URL in the RouteConfig. You could else {
also set as the default URL if you wish. The application SkipBlock(data, ref from) Each StackLevel consists of all of the local variables of the
should look Figure 3. } function being executed (including the passed-in param-
eters) and the function name. This is the name you see in
Lets try throwing and catching exceptions in action with the exception stack.
the factorial function that you saw above. You use the
The redirects happen following CSCS code that has some artificially created ex- Each time you start execution of a new function (regard-
so fast that you ecution stacks for throwing an exception: less of whether its defined in the C# code or in the CSCS
might miss them! code), a new StackLevel is added to the s_locals stack.
function trySuite(n) { You pop up one StackLevel from the s_locals data struc-
print("Trying to calculate the", ture each time you finish the execution of a function.
"negative factorial");
When you click on Get Files, the application tries to do result = tryNegative(n); In the examples, you saw a few functions implemented in
an HTTP call to the server, but is met with a 401 error return result; CSCS. Do all of the scripts have to be in the same file? Can
because you havent authenticated yet. The application } you include other files containing the CSCS code?
should now show you a Login button, as shown in Figure function tryNegative(n) {
4, because you have redirected to the login page. return factorial(-1 * n);
}
Including Other Files Containing
Clicking on the Sign-in button takes you to AzureAD, try { the CSCS Code
whereupon providing the correct credentials results in f = tryNegative(5); To include another module containing CSCS scripts, you
two redirects. Watch closely, because they happen so print("factorial(", n, ")=", f); use the same function approach as with all other func-
20 Title article codemag.com codemag.com How to Write Your Own Programming Language in C# 57
n +")"; string result = arg.AsString();
throw (exc);
} // 3. Throw it!
if (n < 0) { throw new ArgumentException(result);
exc = "Negative number (n="+n+") for factorial"; }
throw (exc); }
}
if (n <= 1) { The try function requires a bit more work, so its easier to
return 1; delegate all the work to the Interpreter, which can tell the
} Parser what to do:
Executing the factorial function with different arguments private Interpreter m_interpreter;
provides the following output: }
try {
Throw, Try, and Catch Control Flow result = ProcessBlock(data, ref from);
Statements }
The try() and throw() control flow statements can be im- catch(ArgumentException exc) {
plemented as functions in the same way that you saw the exception = exc;
implementation of the Round() function above. }
Both functions must be registered with the Parser first If theres an exception, or a catch or a break statement,
as well: you need to skip the whole catch block. For that, go back
to the beginning of the try block and then skip it:
public const string TRY = "try";
public const string THROW = "throw"; if (exception != null ||
result.Type == Variable.VarType.BREAK ||
The implementation of the throw() function follows: result.Type == Variable.VarType.CONTINUE)
{
class ThrowFunction : ParserFunction from = startTryCondition;
{ SkipBlock(data, ref from);
protected override Variable Evaluate( }
string data, ref int from)
{ After the try block, you expect a catch token and the name
// 1. Extract what to throw. of the exception to be caught, regardless of whether the
Variable arg = Utils.GetItem(data, exception was thrown or not:
ref from);
string catchToken = Utils.GetNextToken(data,
// 2. Convert it to a string. ref from);
56 How to Write Your Own Programming Language in C# codemag.com codemag.com Title article 21
ONLINE QUICK ID 1607041
Even so, they continue to be misunderstood despite the Once you have you parameter expression, you can begin
fact that theyve been part of .NET since 2009. In 2010, to build the additional components. The following code
the Dynamic Type was introduced and that gave us the creates an expression constant:
ability to create dynamic lambda expressions.
var constant = Expression.Constant("John");
In this article, Ill break through the numerous convoluted
examples that you may have already encountered and show The expression constant has to be compared to some proper-
you the basics of what you need to get productive right ty. The code in the next snippet creates a property expression.
away with dynamic lambda expressions. Lambdas and ex-
John V. Petersen pression trees can get complex. Instead of focusing on the var property = Expression.Property(parameterExpression,
johnvpetersen@gmail.com minutia, Im going to cut through to the good stuff. "FirstName");
linkedin.com/in/johnvpetersen
@johnvpetersen Note that the parameter expression created earlier is used
Data Classes and Data Set to validate the property. If the property name passed as a
John is a graduate of the Rut-
gers University School of Law To get started, you need a sample data set. Listing 1 il- string isnt found for the specified type, an error is thrown.
in Camden, NJ and has been lustrates the data classes that will be used for the ex-
admitted to the courts of the amples in this article. Listing 2 illustrates the sample Next, you need to bring the expression constant and
Commonwealth of Pennsylvania data set. property together. In this case, you wish to test whether
and the state of New Jersey. or not a property is equal to a string constant. The follow-
For over 20 years, John has ing code brings those two expressions together:
developed, architected,
A Simple Lambda Expression Query
and designed software for Just about every application requires some form of data var expression = Expression.Equal(property, constant);
a variety of companies and access and query capability. Using the data classes and
industries. Hes also a video data set illustrated in Listing 1 and Listing 2 respective- The expression variables string representation is:
course author for Lynda.com. ly, you can employ the following query to find all people
HIs latest course, Foundations with the first name of John: {(person.FirstName == "John")}
of Programming, Open Source
Licensing, teaches everything var result = _people.Where(person => person.FirstName Once an expression has been created, you can create a lamb-
you need to understand about == "John").ToList(); da expression. The next code snippet accomplishes that task:
the legal aspects of open-source
licensing. Lambda expressions, like is the one illustrated above, are var lambda = Expression.Lambda<Func<Person,
very powerful. There is also some inflexibility, although bool>>(expression, parameterExpression);
you can easily vary the value you use to compare to the
FirstName property. What if you want to vary the prop- In this case, the lambda represents a delegate function that
erty? That is, as it turns out, a bit more complicated. accepts a Person argument and returns a Boolean value
to indicate whether the specified Person object meets the
In the next section, Ill convert the query listed above to be query criteria. In this case, the query criterion is wheth-
dynamic so that it can be built and compiled at run time. er the FirstName == John. The following illustrates the
string representation of the dynamic lambda expression:
Creating Your First Dynamic Lambda {person => (person.FirstName == "John")}
Expression
The key to understanding how to create dynamic lambda This is identical to the lambda expression in the simple
expressions rests with understanding the Expressions lambda expression query listed above. The only difference
Class, which is part of the System.Linq.Expressions is that instead of embedding the definition in the code,
Namespace. The first step is to create a parameter expres- youve built it dynamically. The last step before using the
sion that allows you to validate and compile against a dynamic lambda expression is to compile it:
known type. In this case, the type is in the Person and
Address Classes: var compiledLambda = lambda.Compile();
var parameterExpression = Now that the lambda is compiled, you can use it in a query:
Expression.Parameter(Type.GetType("ExpressionTreeTests.
Person"), "person"); var result = _people.Where(compiledLambda).ToList();
22 Simplest Thing Possible: Dynamic Lambda Expressions codemag.com codemag.com Title article 55
Listing 3: Implementation of the Function Creator class Listing 1: Data Classes
class FunctionCreator : ParserFunction args = new string[0]; public class Address public Person()
{ } { {
internal FunctionCreator(Interpreter interpreter) public string Number { get; set; } this.Address = new Address();
{ Utils.MoveForwardIf(data, ref from, public string Street { get; set; } }
m_interpreter = interpreter; Constants.START_GROUP, Constants.SPACE); public string City { get; set; }
} public string State { get; set; } public string FirstName { get; set; }
string body = Utils.GetBodyBetween(data, ref from, public string Zipcode { get; set; } public string LastName { get; set; }
protected override Variable Evaluate( Constants.START_GROUP, Constants.END_GROUP); } public Address Address { get; set; }
string data, ref int from) public class Person public int Age { get; set; }
{ CustomFunction customFunc = new CustomFunction(funcName, { }
string funcName = Utils.GetToken(data, ref from, body, args);
Constants.TOKEN_SEPARATION); ParserFunction.AddGlobal(funcName, customFunc);
m_interpreter.AppendOutput("Registering function [" +
funcName + "] ..."); return new Variable(funcName); Thats it. Thats all there is to building a simple dynamic Listing 2: Data Set
} lambda expression. What if you have compound criteria? private List<Person> _people = new List<Person>();
string[] args = Utils.GetFunctionSignature(data, ref from); Lets tackle that next. var person = new Person();
if (args.Length == 1 && string.IsNullOrWhiteSpace(args[0])) private Interpreter m_interpreter;
person.FirstName = "John";
{ }
person.LastName = "Doe";
Creating a Dynamic Lambda with person.Age = 29;
Compound Criteria person.Address.Number = "1234";
Listing 4: Implementation of the custom function class The following is an example lambda expression with com- person.Address.Street = "Main Street";
person.Address.City = "Philadelphia";
class CustomFunction : ParserFunction StackLevel stackLevel = new StackLevel(m_name); pound criteria:
person.Address.State = "PA";
{ for (int i = 0; i < m_args.Length; i++) { person.Address.Zipcode = "19101";
internal CustomFunction(string funcName, stackLevel.Variables[m_args[i]] = new GetVarFunction( var result = _people.Where(person => person.FirstName ==
string body, string[] args) functionArgs[i]); "John" || person.Address.City == "Paoli" ).ToList(); _people.Add(person);
{ }
m_name = funcName; To duplicate the code dynamically, you can start with the person = new Person();
m_body = body; ParserFunction.AddLocalVariables(stackLevel); same elements as in the first example: person.FirstName = "Bob";
m_args = args; person.LastName = "Smith";
} // 2. Execute the body of the function. var parameterExpression = person.Age = 65;
int temp = 0; person.Address.Number = "123";
Expression.Parameter(Type.GetType("ExpressionTreeTests
protected override Variable Evaluate(string data, Variable result = null; person.Address.Street = "Lancaster Avenue";
.Person"), "person");
ref int from) while (temp < m_body.Length - 1) person.Address.City = "Paoli";
var constant = Expression.Constant("John"); person.Address.State = "PA";
{ {
var property = Expression.Property(parameterExpression, person.Address.Zipcode = "19301";
bool isList; result = Parser.LoadAndCalculate(m_body, ref temp,
List<Variable> functionArgs = Utils.GetArgs(data, Constants.END_PARSE_ARRAY); "FirstName");
ref from, Constants.START_ARG, Constants.END_ARG, Utils.GoToNextStatement(m_body, ref temp); var expression = Expression.Equal(property, constant); _people.Add(person);
out isList); }
Utils.MoveBackIf(data, ref from, Constants.START_GROUP); Next, you need to build up the second expression. This
if (functionArgs.Count != m_args.Length) { ParserFunction.PopLocalVariables(); one is a bit more complicated because the City property expression = Expression.Or(expression, expression2); Lambdas and Expression
throw new ArgumentException("Function [" + m_name + return result; is a member of an object that is, in turn, a member of the Trees
"] arguments mismatch: " + m_args.Length + " declared, " + } Person Class: Person.Address.City. You might think that The rest of the code is like the previous example:
functionArgs.Count + " supplied");
A good resource for further
you could simply write this code:
} private string m_body; details on lambdas and
var lambda = Expression.Lambda<Func<Person,
private string[] m_args; expression trees can be found
var property = Expression.Property(parameterExpression, bool>>(expression, parameterExpression); on the MSDN site: https://msdn.
// 1. Add passed arguments as local variables to the Parser. } "Address.City"); //This will not work microsoft.com/en-us/library/
var compiledLambda = lambda.Compile(); bb397951.aspx.
Instead, you have to traverse the hierarchy in order to
The name of the custom function to be registered is func- Second, the body of the function is evaluated, using the validate nested properties: var result = _people.Where(compiledLambda).ToList();
Name. The Parser expects that the token with the func- main Parser entry point, the LoadAndCalculate() method
tion name will be the next one after the function token. If the body contains calls to other functions, or to itself, Expression property2 = parameterExpression; The following illustrates the generated lambda:
Commas separate the tokens. the calls to the CustomFunction can be recursive. Lets
see this with the factorial example. foreach (var member in "Address.City".Split('.')) {person => ((person.FirstName == "John") Or
All of the functions that you implement in the CSCS code { (person.Address.City == "Paoli"))}
correspond to the different instances of the C# Custom- Example: Factorial property2 = Expression.PropertyOrField(property2,
Function class. The factorial notation is n! and its defined as follows: 0! member); In the next installment, Ill illustrate how to create dynam-
= 1, n! = 1 * 2 * 3 * * n. } ic lambda expressions in the context of dictionaries that
During parsing, as soon as the Parser encounters the consist of a string,object pair. On one hand, string,object
funcName token, it calls its handler, the CustomFunction, In the notation, n must be a non-negative integer. There- With the property expression resolved, you can now join pairs are very flexible in that anything can be stored as
where all the action takes place. You can see the Custom- fore it can be defined recursively as: n! = 1 * 2 * 3 * * it to the constant: an object. On the other hand, querying a dictionary of
Function implementation in Listing 4. (n 1) * n = (n 1)! * n. string,object requires you to cast the object to a specific
In CSCS, the code is the following: constant = Expression.Constant("Paoli"); data type. Add dynamic lambdas to the mix, and the chal-
Custom function does two things. First, it extracts the var expression2 = Expression.Equal(property2, lenge is greater. Ill cover those situations next time.
function arguments and adds them as local variables to the function factorial(n) { constant);
Parser (theyll be removed from the Parser as soon as the if (!isInteger(n)) { John V. Petersen
function execution is finished or an exception is thrown). exc = "Factorial is for integers only (n="+ The next step involves joining the two expressions:
54 How to Write Your Own Programming Language in C# codemag.com codemag.com Simplest Thing Possible: Dynamic Lambda Expressions 23
ONLINE QUICK ID 1607051
24 Support Your Application Post-Launch Intelligently Using Intercom.io codemag.com codemag.com How to Write Your Own Programming Language in C# 53
Finally you must merge two resulting cells: public const string ROUND = "round";
Merge ((0, ||), (0, ")")) = Next, you register the function implementation with the
(0 || 0, )) = (0, ")") Parser:
Figure 2: Running a Client and a Server on a Mac Figure 2: Intercom.io real-time chat window in expanded format on the Web.
52 How to Write Your Own Programming Language in C# codemag.com codemag.com Support Your Application Post-Launch Intelligently Using Intercom.io 25
After the first step, youll have the following cells consist- Merge(("c", ==), ("a", ||)) =
ing of strings and actions: (c, ==), (a, ||), (c, ==), ("c" == "a", ||) = (0, "||").
(b, )). The symbol ) denotes a null action. The last
cell always has a null action. You cant merge the cell (0, ||) with the next one, (c,
==), because the priority of the || action is lower than
The second step consists in merging all the cells one by the priority of == according to the Listing 1. So we
one from left to right. Because the priority of == is higher must first merge (c, ==) with the next cell, (b, )). This
than the priority of ||, the first two cells can be merged. merge is possible and is analogous to the previous one:
The action of the left cell, ==, must be applied, yielding to: Merge((c, ==), (b, )) ) = (0, )).
Once you configure your application to track users and using the platform for longer than x amount of
store this information, you can apply that context to your time.
communication. For instance, lets say that you want to 3. Filter your user base by individuals whove used this
gather feedback for an updated feature that you recently specific feature at least y times.
re-launched. You could solicit your entire user base. How- 4. Filter by individuals who used this specific feature in
ever, consider the following scenarios: the last z days.
5. Send the feedback request only to this subset of users.
Some of your users havent tried this new feature yet
so youve solicited them for information for which
they cant provide a meaningful answer. Because the
context of the communication is irrelevant to them, How can you tell the difference
it could be regarded as spam and, in turn, could dis- between users who frequently
courage them from looking at or responding to future visit your website and use Figure 1: The Parser UML class diagram
messages that may actually be relevant. your app and those whore
Some of your users may have used the feature once just poking around?
or twice, but not enough to really offer you the in- Listing 1: Priorities of the Actions
depth feedback youre looking for. private static bool CanMergeCells(Variable leftCell, case "-" : return 7;
Some of your users have extensive experience Variable rightCell) { case "<" :
with this feature but havent used it since you With this process, you should have a high level of confi- return GetPriority(leftCell.Action) >= case ">" :
re-launched it. You are likely to get a meaningful dence that each returned response comes straight from GetPriority(rightCell.Action); case ">=":
review but on an old product thats no longer ac- the individuals who use it most, giving you the best } case "<=": return 6;
tive, leaving you to guess at whether or not their chance at meaningful feedback. This merely represents case "==":
response applies. one of the many different ways you can use Intercoms private static int GetPriority(string action) { case "!=": return 5;
targeted user metrics. To find out more, check the sidebar switch (action) case "&&": return 4;
How much more efficient would the feedback-gathering for additional use cases. { case "++": case "||": return 3;
campaign be if you could set up the following: case "--": return 10; case "+=":
Managing the Conversation case "^" : return 9; case "=" : return 2;
1. Create an automated message template that ad- Once the user clicks the messaging icon and initiates a con- case "%" : }
dresses the user by name, asking for feedback on a versation, that message is sent to your conversation inbox, case "*" : return 0;
particular feature. as pictured in Figure 3. Conversations start as unassigned case "/" : return 8; }
2. Filter your user base by individuals whove been until one of your application admins assigns it, or responds case "+" :
26 Support Your Application Post-Launch Intelligently Using Intercom.io codemag.com codemag.com How to Write Your Own Programming Language in C# 51
ONLINE QUICK ID 1607081
Here are a few advantages of writing your own language:: separate all CSCS statements. I define it in the Constants.
cs file as Constants.END_STATEMENT = ; constant.
Unlike most other languages, its very easy to modify
functionality because everything is in an easy-to-fol- The Split-and-Merge algorithm consists of two steps.
low standard C# code with a clear interface for func- First, you split the string into the list of tokens. Each to-
tions to be added. Any additional functions can be ken consists of a number or a string and an action that
added to this language with just a few lines of code can be applied to it.
All of the keywords of this language (if, else, while,
function, and so on) can be easily replaced by any non- For strings, the actions can only be a plus sign + (string
Vassili Kaplan English keywords (and they dont have to be ASCII, concatenation) or Boolean comparisons, such as ==, <,
vassilik@gmail.com contrary to the most other languages). Only configu- >=, etc., giving a Boolean as a result. For numbers, there
ration changes are needed for replacing the keywords are a few other possible actions, such as -, *, /, ^, and
Vassili Kaplan is a former This language can be used as both as a scripting %. The prefix and postfix operators ++ and -- and the as-
Microsoft Lync developer. He language and as a shell program, like Bash on Unix signment operators +=, -=,*=, etc., are treated as special
has been writing software since or PowerShell on Windows (but you will make it actions for numbers. For strings, I implemented the +=
the early nineties, studying
more user-friendly than PowerShell). assignment operator only, because I couldnt find a rea-
and working in a few countries,
Even Python doesnt have the prefix and postfix op- son for other assignment operators for strings.
such as Russia, Mexico, the
erators ++ and -- with the killer argument, you dont
USA, and Switzerland.
need them. With your own language, you can decide The separation criteria for tokens are an action, an ex-
He has a Masters in Applied for yourself what you need. And Ill show you how. pression in parentheses, or any special function, previ-
Mathematics with Specializa- Any custom parsing can be implemented on the fly. ously registered with the Parser. In case of an expression
tion in Computational Sciences Having full control over parsing means less time in parentheses or a function, you recursively apply the
from Purdue University, West searching for how to use an external package or a whole algorithm to the expression in parentheses or to
Lafayette, Indiana. regex library. the function with its arguments. At the end of the first
You wont be using any regular expressions at all! I step, youll have a list of cells, each consisting of an ac-
In his spare time, he works on believe that this is the main showstopper for a few tion and either a number or a string. This action is applied
a free iPhone app called iLan- people who desperately need to parse an expression to the next cell. The last cell always has a null action. The
guage. His other hobbies are but are averse to the pain and humiliation induced null action has the lowest priority.
traveling, biking, badminton, by the regex rules.
and enjoying a glass of a good
The second step consists of merging the elements of the
red wine.
This article is based on two articles that I published in list created in the first step. The merging of two cells
You can find how to contact MSDN Magazine (see references in the sidebar). In the consists of applying the action of the cell on the left to
him at his website: first article, I described the Split-and-Merge algorithm to the numbers, or strings of the left and of the right cell.
http://www.iLanguage.ch parse a mathematical expression, and in the second one, The merging of two cells can only be done if the priority
I described how you can write a scripting language based of the action of the left cell is greater than or equal to
on that algorithm. I called that language CSCS (Custom- the priority of the action of the cell on its right. Other-
ized Scripting in C#). For consistency, Ill call the lan- wise, you merge first the cell on the right with the cell
guage that Ill describe in this article CSCS as well. on its right, and so on, recursively, until you reach the
end of the list.
The CSCS language, as described in my second MSDN article,
was not yet very mature. In particular, theres a section to- The priorities of the actions are shown in Listing 1. If
ward the end of the article mentioning some of the impor- they dont make sense for your usage, you can easily
tant features usually present in a scripting language that change them.
CSCS was still missing. In this CODE Magazine article, Ill
generalize the CSCS language and show how to implement Example of the Split-and-Merge Algorithm
most of these missing features and a few others as well. Lets see how to evaluate the following expression: x ==
a || x == b.
The Split-and-Merge Algorithm to First of all, x must be registered as a function with the
Parse a Language Statement Parser (all CSCS variables are registered and treated as
Here, Ill generalize the Split-and-Merge algorithm to functions). Therefore, when the Parser extracts the token
parse not only a mathematical expression but also any x, it recognizes that its a function and replaces it with
CSCS language statement. A separation character must the actual x value, say, c.
50 How to Write Your Own Programming Language in C# codemag.com codemag.com Support Your Application Post-Launch Intelligently Using Intercom.io 27
developer to provide a complete list of Registra- pushgcm.py script is called to send a push notification to
tion IDs of the app installed on the users devices. the Android application. Listing 3 shows the addition.
If you want to send a push message to multiple
recipients, separate the Registration IDs with com- In line #1, you need to import the os module so that
mas (,). when motion is detected you can use the os.system()
#6: The HTTP header to sent to the GCM server to function (in line #2) to perform a shell operationspe-
authenticate the identity of the sender. cifically, to execute the pushgcm.py script.
#7: The content of the push message. Here, youre
sending two key/value pairs, indicating whos
sending the message and the event. For GCM push Summary
messages, you can send multiple key/value pairs. In this article, weve attempted to define what an IoT sys-
The Android application receiving the push mes- tem is and to illustrate it with a very simple and practical
sage simply specifies the key(s) to extract the example: using the Raspberry Pi and detect motion and
value(s). triggering a push notification when one is detected. We
#8: You create a dictionary to store the content of welcome your comments and ideas on the IoT systems
the push message together with the registration that youve built.
ID(s) of the recipient(s).
#9: You set the content of the push message in the Wei-Meng Lee
dictionary.
#10: You set the recipient(s) of the push message.
Figure 4: Create custom rules to trigger automated messages using the Intercom.io dashboard. #11: You use the json.dumps() function to convert Clarence Chng Google Cloud Messaging
the dictionary object into a JSON string so that you
Google Cloud Messaging (GCM)
can print it out to examine its content.
allows an Android application to
to it, in which case it gets auto-assigned. The conversation traditional email inbox, those communications appear in #12: You use the requests.post() function to post receive push notification from an
has an online/offline indicator for the user, letting you pri- your Intercom inbox, as previously pictured in Figure 3. You the push message to the GCM server. application developer even if the
oritize your responses to those active individuals. can assign these inbound communications to specific team #13: After the message was sent to the GCM server, application isnt running.
members, manage who responded to what, notate the con- it responds with the status. Here, you print out the
If you or your team cant respond in real-time, you can versations, and get analytics back on your teams response content type of the response, followed by the status To learn more about GCM, head
set an automated response to let the user know youll get time, conversion rate, etc. Additionally, Intercom stores of the HTTP request, as well as the details of the to https://developers.google.com/
back to them, and you can include a timeframe so that valuable information about each user who contacts you. This sending (such as if the message was successfully cloud-messaging/android/client
they have a reasonable expectation of when to expect way, you can respond smarter and more efficiently. sent or failed to send, the ID of the message, etc.). for a detailed description on how
a response. At that point, the user can leave his email you can enable your Android
address and the conversation can continue offline. Before you can run the Python code to send a push noti- apps to use GCM to receive push
fication to the Android device, you need to download and notifications.
Intercom has several options to make responding to Intercom stores valuable install the Requests Python library. To do that, type the
conversations easier. For instance, you can pre-write information about each user following command in Terminal:
responses to the most frequently asked questions and who contacts you. This way,
summon those responses whenever necessary, to avoid you can respond smarter and $ sudo pip install requests
time spent repeating yourself. If you find yourself in a more efficiently.
conversation and cant answer a users question, you can Once Requests is installed, type the following command
@mention another member of your team to assist. The to execute the pushgcm.py script:
note will only be seen by the mentioned team member
and can provide a useful way to notate details about the Customization $ sudo python pushgcm.py
conversation to be shared among your team. Customization options seem to be the biggest trade off for
Intercoms simple installation and integration process. Al- If the push message is delivered successfully to the GCM
Additionally, you can pro-actively initiate these conversa- though you can choose a general theme color and customize server, you should an output similar to the following:
tions with your users. For instance, consider the scenario the welcome text, there isnt a way to brand the Intercom
where you have a pricing page on your site or app. You could widget to fit the flavor of your existing content. However, this Data to post to GCM Server
set up a rule that says, If the user has visited the pricing seems like a small price to pay for the functionality gained --------------------------
page three times, on the third time, automatically send them with only a few minutes of additional development effort. {"registration_ids": ["<Registration_ID>"],
a message highlighting a video that discusses the offerings Customizing the theme color affects the following elements: "data": {"event": "Motion Detected!",
in more detail. Furthermore, if the user has spent more than "sender": "Raspberry Pi"}}
two minutes on the page, you could send them an automat- The Intercom Messenger button that appears in --------------------------
ed message to see if they need assistance. If they reply, you your app
can pick up the conversation in real-time. Figure 4 demon- The send button in the message window Response from GCM Server
strates the interface to set up a custom rule. The headings in your in-app messages ------------------------
The buttons and links in your messages Header : application/json; charset=UTF-8
Traditional Email Support Gets an Upgrade Status : 200
If you have an existing support system set up using email There doesnt seem to be a way to modify these elements Text : {"multicast_id":8838766867169688347,"succes
contact, Intercom can provide you with an easier way to individually either, so the color chosen is automatically s":1,
manage that inbound communication without disrupting applied everywhere applicable. "failure":0,"canonical_ids":0,"results":
your current workflow. For instance, lets say that you have [{"message_id":"0:1461392749167691%62851a86f9fd7ecd"}]}
an application with a support form that the user fills in and Pricing --------------------------
this form generates an email to you. You could configure Intercom separates its product offering into four distinct use
Intercom using the email address that your support form cases (that you saw in the bulleted list back in the begin- To complete this project, you need to modify the motion-
already uses, and instead of sifting through requests in a ning), each with its own feature set. The price for each fea- detection.py script so that when a motion is detected, the
28 Support Your Application Post-Launch Intelligently Using Intercom.io codemag.com codemag.com Introduction to IoT Using the Raspberry Pi 49
Listing 2: Sending a Push Notification Message using Google Cloud Messaging (GCM) ture set is $49/month. However, once youve added the first - (BOOL)application:(UIApplication *)application
product, each additional feature only adds $4/month to the didFinishLaunchingWithOptions:
import requests #1 post_data['data'] = data #9
$49 you pay for the first. For a full list of plan details and (NSDictionary *)launchOptions {
import json #2 post_data['registration_ids'] = reg_id #10
feature offerings, refer to https://www.intercom.io/pricing. // Initialize Intercom
[Intercom setApiKey:@"{API KEY}"
gcm_url = "https://android.googleapis.com/gcm/send" #3 #convert dictionary to JSON
forAppId:@"{APP ID}"];
post_data_json = json.dumps(post_data) #11
api_key = "<API_KEY>" #4 print }
print "Data to post to GCM Server" Basic monthly Intercom
#replace <reg_id> with your own print "--------------------------" service costs less than cell The last steps for the base set up involve informing Inter-
reg_id = ["<Registration_ID>"] #5 print post_data_json phone service! Even adding com when your user has signed in and out. Inside your log-
print "--------------------------" on features is affordable. in method success handler, add the following line of code.
headers = {'content-type':'application/json', #6 print
'authorization':'key=' + api_key} [Intercom registerUserWithUserId:@"{USER ID}"];
#post the data to GCM Server
#notification payload r = requests.post(gcm_url, data=post_data_json, #12 If your application remembers logged-in states, make
data = { #7 headers=headers)
Integrating Intercom sure to also call registerUserWithId each time your app
"sender" : "Raspberry Pi", print "Response from GCM Server" Lets take a look at the process of setting up and in- launches and checks for the active user session. For in-
"event" : "Motion Detected!" print "------------------------" tegrating Intercom into your existing application. For stance, the following example demonstrates an applica-
} print "Header : ", r.headers['content-type'] #13 the sake of this demonstration, lets look at integrating tion that checks whether the user is already logged-in
print "Status : ", r.status_code with an iOS application. The first thing youll need to do within the delegates didFinishLaunching function.
#create a dictionary to store the data to post print "Text : ", r.text is create an Intercom account. You can do this straight
post_data = {} #8 print "--------------------------" from the homepage at Intercom.io by entering your - (BOOL)application:(UIApplication *)application
email address. Next, it asks you to choose the initial didFinishLaunchingWithOptions:
platform to integrate with. For this demo, choose iOS. (NSDictionary *)launchOptions {
Listing 3: Calling the pushgcm.py from motiondetection.py 4. The developer also needs to write another applica- Last, indicate whether your users need to log in to your if (loggedIn) {
tion to communicate with the GCM server to send application or not. This answer to this question drives //
import RPi.GPIO as GPIO the push notification to a particular user(s). In this which quick install and set-up instructions the platform // We're logged in, we can register
import time
project, well use the Raspberry Pi to send the mes- will provide you with. For this demonstration, choose // the user with Intercom
import os #1
sage to a user via the GCM Server. users must log in. [Intercom registerUserWithUserId:
pirsensor = 4
5. Once the GCM server receives the message, it sends @"{USER ID}"];
GPIO.setmode(GPIO.BCM)
the push notification to the app. Installation and Base Set Up // Carry on as normal
GPIO.setup(pirsensor, GPIO.IN, GPIO.PUD_DOWN) To start integrating Intercom into your iOS application,
To send a push message via Googles GCM server, you can you first must add the Intercom SDK to your project. You
previous_state = False use a variety of programming languages, such as C#, Py- can do this using CocoaPods, one of the simplest methods
current_state = False thon, Node.js, etc. Because Python is already supported to add third-party content to any iOS project. For the sake
in Raspbian, its natural to use it. of this walkthrough, Ill assume that you have a working
while True: understanding of how to install a library using CocoaPods
time.sleep(0.1) Open a Terminal window in the Raspbian OS and create a (if not, please refer to the sidebar). Once youve created a
previous_state = current_state text file by typing the following command: Podfile, add the following line to the file and save:
current_state = GPIO.input(pirsensor)
if current_state != previous_state: $ nano pushgcm.py pod "Intercom"
if current_state:
print("Motion Detected!") Enter the statements as shown in Listing 2. Be sure to Once saved, launch terminal and navigate to the root fold-
os.system("python pushgcm.py") #2 replace the <API_KEY> with that of your own and the er for your project. Make sure that the project is closed in
<Registration_ID> with that of the registration ID of the Xcode and run the following command in terminal:
Android app installed on a device.
pod install
Once the Android application is installed on the Dissecting the Code
device, it needs to register with Google program- As usual, its useful to understand what the code is doing: This automatically downloads the Intercom library and
matically to obtain a registration ID. This regis- creates an .xcworkspace file, if you didnt already have
tration ID uniquely identifies the application on a #1: Import the Requests Python library that helps one. Re-open your project by double clicking that new
particular device so that GCM can push a message you to send HTTP requests to a server easily without project file. Now that youve installed the sdk, navigate
to it. worrying about query strings, form-encoding your to your application delegate and import the library so you
POST data, etc. can access it, as shown in the next snippet. If you plan
Figure 12 summarizes the interaction between the vari- #2: Import the JSON library so that you can print to take advantage of the intercom event tracking across
ous parties in a push notification system. In particular, out the data that was sent to the GCM server in the majority of your application, you could consider add-
it shows how you can use the Raspberry Pi to send push JSON format. ing the import to your pre-compiled header file (.pch),
notifications: #3: The end point for Googles GCM server. so that the library will be accessible everywhere without
#4: The API Key that youve obtained from Google. having to repeat the import on each controller.
1. The Android app sends an activation request to This identifies the application developer sending
Googles GCM Server. the push notification. #import "Intercom/intercom.h"
2. When the registration is successful, the GCM Server #5: The Registration ID(s) of the application re-
returns a Registration ID to the app. ceiving the notification. You get this Registration Next, back in your application delegate, you want to ini-
3. In the real world, the Registration ID should be sent ID from the application after it has registered tialize the library using your Intercom API Key and Appli-
to a server maintained by the developer, who will with Google. In the real world, this Registration cation ID. Within your didFinishLaunching function, add Figure 5: Intercoms user analytics with additional
then save it into a database. ID should be sent to the server maintained by the the call thats shown in the following code sample. custom fields.
48 Introduction to IoT Using the Raspberry Pi codemag.com codemag.com Support Your Application Post-Launch Intelligently Using Intercom.io 29
BCM numbering scheme. That means that when we Acting on the Sensor Data Pull-Up and Pull-Down
Resistors
say were getting the input from pin 4, were refer-
Now that the PIR Motion sensor is sensing motion, lets
ring to the pin printed as #4 on the T-Cobbler Plus.
put it to good use. A good application of this project is to A GPIO pins value floats between
#5: Initialize the pin represented by the variable
install the Raspberry Pi and the motion sensor at home to 0 and 1 if it isnt connected to
pinsensor as an input pin. Also, we use a pull-down
monitor for unexpected movement. You could mount the voltage. This is known as floating.
resistor (GPIO.PUD_DOWN) for this pin.
sensor near your door to detect movement outside the In the case of the GPIO pin
#6: There are two variables to keep track of the
house when theres no one at home. connected to the output value of
state of the sensor.
the PIR Motion Sensor, the GPIO
#7: We use an infinite loop to check the state of the pins value is undefined before
sensor repeatedly. the sensor detects any motion.
#8: Inserts a slight delay of 0.1 second to the ex- When the PIR Motion Sensor In this case, you need to use a
ecution of the program detects motion, its output pull-down resistor to always pull-
#9: Save the current state of the sensor. will be 1 (true), and a few down (GPIO.PUD_DOWN) the
#10: The GPIO.input() function reads the value of seconds later, its automatically value to 0, so that you can be sure
the GPIO pin (#4 in this case). When motion is de- that the only time the pin value
reset to 0 (false).
tected, it returns a value of true. changes to 1 is when the sensor
#11: Compare the previous state and the current detects motion.
state to see if the motion sensor has a change in
state. If theres a change, it means that either the Once motion is detected, the Raspberry Pi could send a Likewise, you can also configure
sensor has just detected motion (when the state push notification to an Android device via the Google Cloud a GPIO pin using the pull-up
Intercom Integrations changes from false to true), or that the sensor is Messaging (GCM). A detailed description of Android and resistor (GPIO.PUD_UP). Instead
resetting itself (when the state changes from true GCM is beyond the scope of this article, but heres whats of setting a pin value to always
Intercom integrates with several 0, a pull-up resistor pulls-up the
to false) a few seconds after motion has been de- required for an Android app to receive a push notification:
third parties, out of the box, value to 1. This is useful in cases
including WordPress, GitHub, tected.
where some sensors (such as
Stripe, and several others. #12: If the current state is true, it means that mo- The developer of the Android application needs to
push buttons) set the GPIO pin to
Check out the full list here: tion has been detected. apply for an API key at https://console.developers. 0 when triggered (e.g., the button
https://www.intercom.io/ #13: Print out the string Motion Detected! google.com. is pushed).
integrations
Figure 6: Intercom conversations list (left) and new conversation composer (right).
30 Support Your Application Post-Launch Intelligently Using Intercom.io codemag.com codemag.com Introduction to IoT Using the Raspberry Pi 47
available. If the application is in the foreground, or the
} user opens the app when theres a new message to be
}]; read, a small widget appears over the application with an
indicator that a message is waiting. If the user interacts
Note that email and name are standard fields and that with the widget, they launch into the same conversation
their keys cant be changed. Custom fields must be em- list that you can summon manually. Figure 6 demon-
bedded under the key custom_attributes, as shown in strates what the conversation list and message composer
the previous snippet. You can use any number of custom looks like.
attributes with custom key names inside this section. The
end result in Intercom will resemble Figure 5.
46 Introduction to IoT Using the Raspberry Pi codemag.com codemag.com Support Your Application Post-Launch Intelligently Using Intercom.io 31
ONLINE QUICK ID 1607061
Go
The GPIO pins on the Raspberry Pi are divided into the The Parallax Motion sensor has three pins (see Figure 10):
following groups:
GND: The Ground pin. Connect this pin to the GND
Power: Pins that are labeled 5.0v supply 5 volts of on the GPIO.
Longtime readers of CODE Magazine will recognize that Im very much a lover of programming languages; in addition to being power and those labeled 3V3 supply 3.3 volts of VCC:L The voltage pin. Connect this pin to one of
an F# MVP (I wrote the first F# language article for CODE a few years ago), and writing code in Java, C#, JavaScript, and iOS on power. There are two 5V pins and two 3V3 pins. the 5V pins on the GPIO.
GND: These are the ground pins. There are eight OUT: The output pin. Connect this to one of the In-
a regular basis, I love to dally with other languages as I find them. Ive written Ruby (both for its native execution environment ground pins. put/Output pins on the GPIO.
Input/Output pins: These are the pins labeled with
as well as for the JVM and CLR variants), ML (for both Enough fluff; lets Go (pun intended) and write some the # sign, for example, #17, #27, #22, etc. These When the PIR Motion sensor detects motion, it outputs a
native and JVM variants), OCaml, Nemerle, Boo, Haskell, code. Its going to be a whirlwind, so strap in and hang pins can be used for input or output. high signal on its output pin. You need to write an applica-
Frege, Clojure, Scheme, Lisp, D, and Ive even sometimes on. Ready? I2C: I2C is a serial protocol for a two-wire interface tion to read the value of this output pin. Figure 11 shows a
written my own. to connect low-speed devices like microcontrollers, PIR Motion sensor connected to the T-Cobbler Plus.
EEPROMs, A/D and D/A converters, I/O interfaces,
Yes, I admit it, I have a problem. But hey, its better than Installation and other similar peripherals in embedded systems.
being addicted to Flintstones reruns, and besides, I can Getting Go isnt difficult and its free. The Go language These pins are labeled SDA and SCL.
quit anytime I want. Really. website (https://golang.org) has an easy top-level link UART: The Universal Asynchronous Receiver/ Depending on the PIR Motion
that takes visitors to an install page (https://golang. Transmitter allows your Raspberry Pi to be con- Sensor that youre using,
Ted Neward Thus, it was with no hesitation that when Rod Paddock org/doc/install) containing installation instructions; on nected to serial peripherals. The UART pins are la- the arrangement of the
was looking for someone to tackle the Go language for a Mac, its as easy as brew install go (assuming you beled TXD and RXD. various pins isnt always in
Ted Neward is the CTO of iTrellis, CODE Magazine, I was quick to throw my virtual hand into have Homebrew installed; if you dont use Homebrew, se- SPI: The Serial Peripheral Interface is a synchro-
a software development consul- the same order as described.
the air. (Actually, I threw my real hand in the air, and then riously, whats wrong with you?), and on Windows, theres nous serial communication interface specification
tancy located in Seattle. Hes realized that he couldnt see it over Twitter. The others on an MSI for easy installation. used for short distance communication, primarily in Its important to verify and
an internationally recognized the airplane around me, however, were a little confused.) embedded systems. The SPI pins are labeled MOSI, connect the correct pins to the
speaker, instructor, consultant, Bear in mind, however, that its impossible to explore ev- Once installed, however, Go requires a little bit more MISO, SCLK, CE0, and CE1. correct GPIO pins. Connecting
and mentor and spends a great ery nook and cranny of a language in a single magazine configuration (regardless of platform) before you can get ID EEPROM:Electrically Erasable Programmable the wrong pins to the Raspberry
deal of time these days focus-
article; there are interesting bits of syntax that Im delib- going. Contrary to the attitude espoused by other lan- Read-Only Memory is a user-modifiable read-only Pi can permanently damage
ing on languages and execution
erately passing over, so consider this a teaser designed to guages (C, C++, C#, and so on), Go puts requirements memory that can be erased and written to repeat- the PIR Motion Sensor.
engines like the JVM and CLR.
make you want to explore further. down around the physical arrangement of files (source edly through the application of higher than normal
and otherwise). Specifically, Go requires that Go code electrical voltage. The two EEPROM pins on the
Shall we? live inside of a workspace, which is a physical directory Raspberry Pi (EED and EEC) are also secondary I2C
thats the directory tree in which youre developing your ports that primarily facilitate the identification of Pi In the figure, the red line is the VCC and should be connect-
program. This workspace must be listed in the GOPATH Plates (e.g., Raspberry Pi Shields/Add-On Boards) ed to the 5V pin on the GPIO. The yellow line is the OUTPUT
History and Motivation environment variable before most of the tools will be able that are directly attached to the Raspberry Pi. and is connected to pin #4 on the GPIO. The black line is
In March of 2012, when Google first released version 1.0 to operate correctly. Thus, for example, on my Mac, I can the GND and should be connected to GND on the GPIO.
of Go, it was met with a curious mix of skepticism and ex- point GOPATH to my local directory by writing:
Connecting to a Sensor
citement. Many observers were excited about it, because
to Detect Motion Bonding the Raspberry Pi and
the principals involved in its inception, Brian Kernighan export GOPATH=`pwd`
and Rob Pike, have been longtime contributors to some To demonstrate how to use the GPIO to connect to an ex-
the Sensors: The Python
very positive and popular tools and projects. (Kernighan, This is a bit of Bash shell magic that takes whatever the ternal sensor, well now use a PIR motion sensor to detect Programming Language
in particular, is the first half of Kernighan and Ritchie, the contents of pwd (print working directory) are and sets motion. For this, I used the Parallax PIR Motion Sensor Now that the Raspberry Pi is connected to the PIR Motion
authors of the seminal book on C, also known as the K&R that to be the contents of the GOPATH environment vari- (see Figure 9). The PIR Sensor detects motion by mea- Sensor, its time to write the code to make things work. In
book.) Others, however, were skeptical, owing to senti- able. (Its /Users/tedneward/Projects/Publications/Ar- suring changes in the infrared (heat) levels emitted by the Raspbian OS, Python is a first-class citizen, and the sup-
ments like the world doesnt really need another systems ticles/CODRGo as I write this, just in case you were won- surrounding objects of up to three meters. port for Python comes right out of the box. With its clean
language, and mutterings about Googles intentions dering.)
around it. (For the record, I was in the latter category
for several yearsI didnt think it had much of a chance.)
By the time the most recent release, Go 1.6, shipped in GOPATH can contain
February of 2016, many of the naysayers had forgotten as many dictionaries
about Go, changed their minds, or simply moved on. Qui- as you need.
etly but steadily, Go has gained ground, slowly becoming
a viable candidate for building systems. Its been used in
several interesting projects, including Hugo (https://go-
hugo.com) and the smaller project thats the engine I use This environment variable is highly reminiscent of the
for my new blog, for example. It may not replace C or C++ Java CLASSPATH environment variable, as they are both
as the main player for building native executables any used for exactly the same thing: to help the Go compiler
time soon, but its had seven releases in a fairly stable resolve import statements. In other words, when you
cadence across the last four years, and shows no signs of compile Go code, Go looks at the contents of GOPATH, and
slowing down. starts looking for dependent libraries underneath that di-
rectory. Convention holds that GOPATH contains only one
Thus, its time to take a serious look at the languageeven directory statement, but in fact (as the Go command-line
if you never end up using it on a project, it has some in- documentation will tell you if you type go help gopath
triguing ideas around the design of code and programming once Go is installed on your computer), it can contain as
languages, and chances are that theres something in many different directories as desired, so long as they are Figure 10: The layout of the various pins on the PIR
those ideas that can be useful on your next .NET project. appropriately separated (using a semi-colon (;) on Win- Figure 9: The Parallax PIR Motion Sensor Motion Sensor
Figure 7: Connecting the Adafruit Pi T-Cobbler Plus to Once the Raspbian OS is installed, you can proceed to log
the Raspberry Pi into it and see a full windowed system (see Figure 5). The
default username is pi and the password is raspberry.
If you cant remember which By the way, youve just seen how an if worksnotice how Finally, I just cant end the article without one more pun:
format code goes with the parentheses from C# are missing? Go doesnt need the Good luck with your Go research, and remember, no mat-
which types, fall back to parentheses to surround the true/false expression. (As a ter what, keep Going!
the generic %v. matter of fact, most languages require them out of habit,
not need.) Ted Neward
36 Go codemag.com codemag.com Go 41
referenced in the go command are immediately scheduled nel by calling <- buffer, storing the value returned into the for loop requires some Boolean expression, which Entering DemoDefer
for execution by a goroutine. a local variable. (Yes, thats the left-angle-bracket and is evaluated continuously (before each iteration of the Exiting DemoDefer
the hyphen; think of them as a new operator, like the as- loop) until the condition yields false. In defer the second time
Goroutines arent threads, despite the surface appear- signment operator, but consuming an element out of the In defer the first time
ance, and any synchronization between goroutines re- channel as its doing the assignment.) for a < b {
quires the use of the final Go complex type, a channel. a *= 2 Notice that the deferred expressions are executed in the
The channel acts as a bounded buffer between gorou- Once that channel is empty, Consume sends a message on } reverse order of their definitionits exactly stack-like
tines, unidirectional in nature and allowing any sort of a second channel (quit) to tell the main goroutine that behavior (and it mimics the C++ object destructor rules,
type to be placed within it. When pulling from the chan- its time to quit; otherwise, without this quit channel, When combined with the preceding executable statement not that anybodys intrigued by that besides me).
nel, the goroutine is blocked until theres a value avail- main finishes and terminates before the producer and ability, you have the ability to mimic a classic C-style for,
able, and when pushing into the channel, the goroutine consumer get their chances to do their respective things. like this: Lets keep moving.
is blocked unless the channel has room for the value. By The main goroutine needs to block on quit until it re-
default, channels can hold one strongly typed value, un- ceives the signal, giving me a chance to show you some for i := 0; i < 10; i++ {
less declared to hold more. more syntax: f(i) Complex Go Types
} I said earlier that Go lacks any sort of object facilities. This
Adapting from a popular Java producer-consumer concur- buffer := make(chan string, 4) is true, but Go does allow you to define three different
rency example, you create two functions, one that pro- quit := make(chan int) Most often, however, a for iterates across a range of val- kinds of more complex types: arrays (which look an awful
duces a string by pushing it into a shared buffer (a chan go Produce(buffer) ues (such as that in a collection), similar to the foreach in lot like C-style arrays), structures (which look an awful lot
string in Go terminology): go Consume(buffer, quit) C#, and thanks to destructuring assignment, the for returns like C-style arrays), and maps (which look an awful lot like
both an index and the current element if you wish, like this: C# System.Collection.Generic.Dictionary<> types).
func Produce(buffer chan string) { select {
lyrics := [4]string{ case <-quit: var a [10]string Arrays are the easiest one to define: using the [] syntax,
"Mares eat oats", fmt.Println("quit") for i, s := range a { you can define a collection of singly typed elements into
"Does eat oats", } // type of i is int continuous storage, like so:
"Little lambs eat ivy", // type of s is string
"Wouldn't you like to eat ivy too"} Notice that buffer and quit are both constructed using // s == a[i] as := make([]int, 10, 100)
the built-in make function again. The buffer channel is g(i, s)
for _, s := range lyrics { declared to be four elements in size, allowing the Produce } This creates an array of integers, currently ten items in
buffer <- s function to run at full-tilt, but the code would work just as length (but everything will be initialized to 0), and with a
} well if the buffer were only one element in sizeit ping- Ill talk about what that a is and what a range is in a sec- top capacity of 100 elements in size. Notice the difference
pongs back and forth between Produce() and Consume() ond. You can probably guess, and youre about half right. only ten items are currently allocated, but the Go runtime
close(buffer) until all the messages have been consumed. (Heres a makes room for up to 100. Its an array, like C#-style arrays,
} simple exercise for those following the code on their lap- Go also has switch statements, which have the ability to do but it can be appended and grown, like a List<T>, up to a fi-
tops: put some Println() statements into Produce() and the prefixing statement that if has. Switch can also switch nite amount. The make here is a built-in function, similar in
Notice that the Produce function calls the built-in close Consume() and prove this.) Then main() uses the go key- on the type of a variable (rather than its value), if desired. concept to C#s (or Javas or C++s) new Go also uses new,
function on the channel when the array has been fully word to launch Produce() and Consume() on goroutines, but under different circumstances, and like make, new is
pushed into the channel. This is how the consumer knows and uses the select keyword, which is much like a switch, just a built-in function with no other special syntax or rules.
that theres nothing left to consume. to block until the quit channel produces a value (that you Several other built-in functions can manipulate an array (ap-
ignore, because merely being signaled is enough). Go also isnt only resting pend, copy, and delete, for example), and Ill leave it to the
on the traditional C-family Go documentation to fill in those details.
Theres much, much more that can be explored here, par- constructs.
The code works just as well if ticularly since Gos simplicity around concurrency enables The related type slices are essentially sub-ranges of an
a number of very elegant solutions to some very compli- underlying array. For example, you can take a slice of the
the buffer is only one element
cated concurrent execution, pushing it in terms of time above array by taking the values from the second posi-
in sizeit ping-pongs back (and cognitive capacity). But Go also isnt only resting on the traditional C-family tion through the fifth by asking for them using the []
and forth between Produce() constructs; in addition to the above, Go has introduced a operator. (Technically, when you index into the array for a
and Consume() until all the new control construct, defer, which takes an expression (or single element, youre getting a slice of length 1.)
messages are consumed. Summary an anonymous function block) that will be executed when
If you made it this far, congratulations, particularly if you this block of code terminates. In other words, Gos defer Maps are, like arrays, a collection of elements, but these
made it all the way through in one reading. This wasnt provides destructor-like syntax but without having to de- are associative arrays, meaning that you can define the
an easy ride; take a deep breath, let it out slowly, and let fine an explicit IDispose interface implementation or com- keys used to identify the elements stored within. Creating
Next, you define a Consume function that reads from that your mind clear for a moment. plicated C++-style destructor rules. You could write this: a map of strings to integers, for example, looks almost
channel until theres nothing left to read: identical to the array syntax, except that now the type
The key takeaways here about Go are fairly straightforward. func DemoDefer() { descriptor is slightly different:
func Consume(buffer chan string, quit chan int){ First, Go is a system-level language; its not intended to ex- fmt.Println("Entering DemoDefer")
for msg := range buffer { ecute on top of a virtual machine. As a matter of fact, a num- ages := make(map[string]int, 100)
fmt.Println("We received:", msg) ber of projects are exploring using Go as the source language defer fmt.Println("In defer the first time") ages["Ted"] = 45
} for a virtual machine for other languages. Most of the time, ages["Charlotte"] = 29
Go wont be the language with which developers build the defer func() { ages["Michael"] = 23
quit <- 0 front-end, but rather the infrastructure and/or the back-end fmt.Println("In defer the second time") ages["Matthew"] = 16
} services. (As a matter of fact, the Go standard library has }() for i, a := range ages {
extensive support for various network protocols, encryption, fmt.Printf("%v is %v years old\n", i, a)
The for loop here automatically pulls from the channel and network security, and wire representations like JSON.) fmt.Println("Exiting DemoDefer") }
(because you use it as the source of the for loops data); }
this is a pretty common thing to do. Were this not the As an example of what can be done very elegantly in Go, con- This creates a map of 100 string/integer pairs (the capac-
case, Consume could pull a single value out of the chan- sider the NATS message server, available at http://nats.io/ When its executed, Go prints out: ity is assumed to be the same as the length if no other
40 Go codemag.com codemag.com Go 37
value is given), all of which will be initially empty. You must be upper-cased as well. Again, this is how Go de-
type Person struct { Note that if a Go developer absolutely cant live without
FirstName string something that looks like an object, you can always de-
LastName string fine fields of a struct to be of function types (func(int)
Age int int for a function that takes an int and returns an int),
} created using a constructor function such as NewPerson
defined in the goperson package. (In fact, idiomatic Go
Note that youve defined this in a new library, goperson; prefers such a function over using the initializer syntax
this is so you can demonstrate how Go can support re- that I used above.) Packages go a long ways toward mas-
mote libraries. Back in the main package, you need to add querading as objects, and clever use of functions and
the code that uses the Person type, but more importantly, structs can remove all but the most strenuous objections
you need to import it as usual: (pun intended).