To set up dual monitor displays at Windows 10, right-click in the taskbar, pick "Properties" and then click "Customize..." and then from the "System" box that appears go to "Display" and start by changing "Multiple displays" to: "Extend desktop to this display" ...you know, I've kept this blog for 5+ years and only now am I using an operating system at work that is newer than the blog itself. (not Windows 7)
Tuesday, November 15, 2016
Monday, November 7, 2016
abstraction: the fourth pillar
I thought there were three pillars to OOO as suggested here. In Googling it some, it kinda seems like some lists include abstraction as a fourth pillar. In many ways this is a lot like encapsulation in that in both cases you are trying to expose what is important and marginally hide that which is merely necessary that should draw the eye less sort of like the distinction between the "Wizard" of Oz and the man behind the curtain. (We want to keep him behind a curtain.) However, that said, encapsulation is something in particular, very particular, and has to do with how gunk is kept in a class itself. Abstraction will have you pulling stuff out of a class to another class.
Addendum 2/22/2019: OOO stands for Out Of Office and really OOO here should be OOP for Object-oriented programming.
Use the ES6 fat arrow for simple function substitution.
var x = y => alert(y+y);
x("hi");
...which is gonna tell you "hihi" is bascially the same as...
var x = function(y){
alert(y+y);
};
x("hi");
There is a way to "autoseek" dependencies in web forms with StructureMap as one does in MVC where they may now auto-hydrate at controller constructors.
I spoke to someone who has done it before over a phone screen just now. It's nasty. You have to inject something into the HTTP model to catch a page before it complies code but after it's baked and inject stuff. Is ObjectFactory that evil that I should want to go there?
closures in JavaScript
What I suggest here is probably really wrong. Instead if you just Google against this topic you'll find stuff like this giving a different explanation. Alright, consider this:
var myClosure = function() {
counter++;
alert(counter);
};
myClosure();
myClosure();
myClosure();
It's gonna fail, right? You can't do plus plus on something undefined, right? Well, what if counter did correspond to a number in a backing store, someplace where state could be kept? It can. You can have this:
var myClosure = (function() {
var counter = 0;
return function() {
counter++;
alert(counter);
}
})();
myClosure();
myClosure();
myClosure();
This code will not break and will moreover throw up three alerts, one after the other, with 1, 2, and 3, in them. We have made counter a privately-scoped variable really only approachable by myClosure and we are using it as a backing store for state. After initial assignment, myClosure behaves in the code immediately above just as it does in the code at the very top of this blog posting. The only difference is that now counter means something.
Saturday, November 5, 2016
yet more RANDOM notes from trying to find a job
a lot of this is shamelessly stolen from other stuff I found online...
- var x = y.OrderByDescending(z =>
z.Date).ThenByDescending(z => z.Name).Skip(5).Take(8);
...is an example of .ThenByDescending/.Take/.Skip in a Lambdaland. - cookies are a long-standing way of maintaining state at the browser while sessionStorage and localStorage are new to HTML5. localStorage lasts until you get rid of it, cookies may be set to last X number of days or minutes, and sessionStorage only lasts until the browser closes
- data- attributes in HTML! You may invent your own "legitimate" inline parameter at an HTML tag to make it easy to latch onto the tag in JavaScript or communicate things in JavaScript.
- The Discovery web service is a tool used to determine the organizations that a user is a member of in Microsoft Dynamics CRM.
- Use both yield return and yield break TOGETHER...
while (true)
{
if (i < 5)
{
yield return i;
}
else
{
yield break;
}
i++;
}
super-simple example of using a directive at a custom tag in an AngularJS 1.5.8 application
Assuming the HTML at the top of this, let's place a new tag just inside the first div tag with the ng-app on it like so:
<add-Intro></add-Intro>
Alright, our directive itself looks like so:
app.directive("addIntro", function () {
return {
template: "Books by George R. Martin:"
};
});
Notice that the names don't match up one for one. You will have a directive name in camelCase and when you call to it with a tag in the markup then the names get hyphens between the words. Whatever. The copy in the template ends up painted to the screen at the tag's locale. Yippee! Anyways, if this seems like a pretty weak blog posting, it really is a wrap-up of a series of other blog postings. This is the sixth of six blog postings in which I build out an AngularJS app. I worked with Angular for like two weeks at @hand three years ago and of course I've forgotten it all so I've been trying to refresh myself. If you follow the following postings you could build out an app yourself!
I think it's neat that the first eight Roman numeral numbers come in alphabetic order, though I suppose that's off topic, eh? Anyways, I recommend just pulling Angular 1.5.8 from NuGet in Visual Studio and building out inside of the first web page your application surfaces when you run it. Add script tags for angular.min.js and angular-route.min.js. Hmmmm... I'm not sure I needed angular-route.min.js.
ng-class/ng-click, Array.isArray, and bolting your own properties onto API data for convenience sake
I've used ng-class and ng-click to make an expandable/collapsible menu in an AngularJS 1.5.8 application. Specifically, I have beefed up the HTML in the app I suggest here like so:
<div ng-app="myApp" ng-controller="myCtrl">
<div ng-repeat="books in booksWrapper">
<div class="outerTemplateWrapper" ng-repeat="book in books">
{{ book.name }}
<div class="middleTemplateWrapper">
<div class="innerTemplateWrapper">
<div class="innerTemplateWrapperLeft">{{ book.isbn }}</div>
<div class="innerTemplateWrapperRight">
{{ book.numberOfPages|sOnTheEnd:"page" }}</div>
<div class="innerTemplateWrapperBase">
<div class="plusOrMinus" ng-class="book.toggleState ? 'plus' : 'minus'"
ng-click="characterCollector(book)"></div>
<div class="characters">characters</div>
<div class="secondInnerTemplateWrapperBase">
<ol ng-class="book.toggleState ? 'displayNone' : 'displayBlock'">
<li ng-repeat="hydratedCharacters in book.hydratedCharactersWrapper">
<span ng-repeat="hydratedCharacter in hydratedCharacters">
{{ hydratedCharacter.name }}
</span>
</li>
</ol>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
My controller has changed up some like so...
app.controller("myCtrl", function ($scope, apiGetter) {
var currentUrl = "http://www.anapioficeandfire.com/api/books";
$scope.booksWrapper = apiGetter.goGetIt(currentUrl).$$state;
$scope.characterCollector = function (book) {
book.toggleState = !book.toggleState;
if (!book.hasHydratedCharacters) {
book.hasHydratedCharacters = true;
var counter = 0;
book.characters.forEach(function (characterUrl) {
if (counter < 10) {
var character = apiGetter.goGetIt(characterUrl).$$state;
book.hydratedCharactersWrapper.push(character);
}
counter++;
});
}
};
});
So it's still getting data upfront for a list of Game of Thrones books and now it is also fishing for new data. The API doesn't include characters for the books with the books, instead it has a list of URLs to hit to make API calls for each character and... well... let's get the first ten characters for each book. The service I made for the API calls is going to change too:
app.service("apiGetter", function ($http) {
return ({
goGetIt: goGetIt
});
function goGetIt(whereToLookTo) {
var request = $http({
method: "get",
url: whereToLookTo
});
return (request.then(handleSuccess, handleError));
}
function handleError(response) {
alert('something went wrong');
}
function handleSuccess(response) {
if (!Array.isArray(response.data)) {
return (response.data);
} else {
var dataPlus = new Array();
response.data.forEach(function (book) {
book.toggleState = true;
book.hasHydratedCharacters = false;
book.hydratedCharactersWrapper = new Array();
dataPlus.push(book);
});
return (dataPlus);
}
}
});
Basically, for the array of books that comes back upfront I want to bolt on my own properties per book, but for the characters themselves, I just want to hand them back as is. The three properties I bolt onto each book are an empty array for eventually later spooling up the characters in and two flags for if that array has been hydrated yet (we don't want to do it over and over) and if an expandable/collapsible menu for showing the array's contents is sitting open. Some CSS is driven by the later flag. It looks like this:
.plus:before {
content: "+";
}
.minus:before {
content: "-";
}
.displayNone {
display: none;
}
.displayBlock {
display: block;
}
Every div with the plusOrMinus class on it, containing cursor: pointer; as a style by the way, is now a button! Clicking the button will change a plus sign to a minus sign or a minus sign to a plus sign based upon the flag for this state. It will also hide or unhide an ordered list in another div which has the list of characters!
an excuse to use a filter in an AngularJS 1.5.8 app
A coworker once showed me an example of a filter that he wrote which pluralized some (a majority) of English words correctly. I'm ripping off his idea here:
app.filter("sOnTheEnd", function () {
return function (number, word) {
if (word === undefined) {
return number;
}
var pattern = number + " " + word;
if (number == 1) {
return pattern;
} else {
return pattern + "s";
}
};
});
I call out to it with the double curly braces syntax like so:
{{ book.numberOfPages|sOnTheEnd:"page" }}
You will note that I've baked in some extra love to keep "undefineds" from showing up in the HTML when this is attempted:
{{ book.numberOfPages|sOnTheEnd }}
Get data from a $http AJAX call into $scope and then into an ng-repeat in an AngularJS 1.5.8 app.
I struggled with this some this morning. The trick is to have a loop inside a loop like so:
<div ng-app="myApp" ng-controller="myCtrl">
<div ng-repeat="books in booksWrapper">
<div class="outerTemplateWrapper" ng-repeat="book in books">
{{ book.name }}
</div>
</div>
</div>
I'm using the same service I suggest here for $http although my controller has changed up some. It now looks like this:
app.controller("myCtrl", function ($scope, apiGetter) {
var currentUrl = "http://www.anapioficeandfire.com/api/books";
$scope.booksWrapper = apiGetter.goGetIt(currentUrl).$$state;
});
That looks plain as day, right? And you wouldn't think I'd need a loop inside of a loop, right? Why the nesting? Well, if you just have one loop you will notice two placeholders appear in the HTML (try to repeat divs or Xs or something) and the second of the two will appear a bit after the first. I suspected the second item was the results coming back from the API asynchronously. At first I had the usual I-hate-the-asynchronous anger of a C# developer and longed to find a way to delay until the second item came back and to isolate it and assign that to scope, but that wouldn't have been terribly mature on my part, huh? The better thing to do is to just build something that accommodates an object with a first property to ignore and a second property to coddle and care about (kinda like how a dad only loves his second son in both Gattaca and Filth). It's easy when only the second property is an array as only the second property can fill out a second loop. If you throw $scope.booksWrapper to the console in myCtrl, you can see the two things on it. In Google Chrome's console, the first is immediately there and the second comes in when it can.
- Object
- status: 1
- value: Array[10]
- __proto__: Object
Bonus: I never could figure out how to get at the snipping tool in Windows 8, though I sort assumed it was there. I found it in Windows 10 this morning. Just type "snip" at that thing at the lower left which says: "Ask me anything"
Friday, November 4, 2016
How to make an API call in an AngularJS 1.5.8 application.
Alright, starting with the very simple application I suggest here, I am going to revamp my token controller from:
app.controller("myCtrl", function ($scope) {
$scope.firstName = "John";
$scope.lastName = "Doe";
});
...to...
app.controller("myCtrl", function ($scope, apiGetter) {
$scope.currentUrl = "http://www.anapioficeandfire.com/api/books";
var content = apiGetter.goGetIt($scope.currentUrl);
console.log(content);
});
I bet you can kinda tell what the revamped myCtrl is gonna to do, right? It's gonna hit the http://www.anapioficeandfire.com/api/books endpoint and barf what it collects from it up to the console. It is going to use apiGetter to do its magic, right? What is that. That's a service. I followed this for that! It appears you may just list the names of services you want in scope in a controller as variables in the function signature for the controller. My service looks like this:
app.service("apiGetter", function ($http) {
return ({
goGetIt: goGetIt
});
function goGetIt(whereToLookTo) {
var request = $http({
method: "get",
url: whereToLookTo
});
return (request.then(handleSuccess, handleError));
}
function handleError(response) {
alert('something went wrong');
}
function handleSuccess(response) {
return (response.data);
}
});
The last of the links I give suggests the three functions are "methods" and makes a distiniction between public and private methods. The goGetIt method is made public by way of being on the object in the return above all the methods. You could have many comma-seperated methods as properties here if you need more than one. It took me a while to realize that I needed to add goGetIt to what is returned in order for myCtrl to be able to use it dotting off of apiGetter. That is what makes it "public" so to speak.
A friend gave me an Angular2 app just now.
I was told to navigate to where I unpackaged it from its tarball to at the command prompt and to then type npm install followed by npm start. The second command actually brings the app up in a browser. Both commands worked. I typically have no luck at all with the npm stuff on my PC laptop, but this time it behaved. Nothing broke. Under the root of the project there is a "node_modules" folder and within that there is an "angular2" folder.
Thursday, November 3, 2016
SparkHire
...is an interesting tool for recording videos of applicants being interviewed by canned, pre-defined questions. I had an interview over SparkHire against ten generic ASP.NET questions and it was pretty slick. I could think about a question for X minutes, then have X minutes to record a video of myself answering. There could be X number of takes and I could review a take before approving it. The Xs are all set as variables by whoever preps the interview.
Make a Razor ActionLink open the link's URL up in a new tab.
@Html.ActionLink("touch me", "Index", "Home", null, new { target = "_blank" })
do NOT do this instead...
@Html.ActionLink("touch me", "Index", "Home", new { target = "_blank" })
...as this will make ?Length=4 appear at the end of the URL at the new tab.
some notes from trying to get an Angular app up and running
- install-package AngularJS at the NuGet command prompt installs AngularJS 1.5.8
- https://github.com/mgechev/angular-seed is an Angular2 seed project
- http://markdownpad.com/ is a Markdown editor for Windows and you should be able to read a README.md with it
- Yarn is a tool for caching locally downloaded dependencies
- Install-Package angular2.TypeScript.DefinitelyTyped will install some Angular2 scripts, including TypeScript, at a Visual Studio project but it will loops in TypeScript which cannot compile in alpha files
- http://blogs.msmvps.com/ was recommended as a good resource
- There is no way to upgrade from Angular 1 to Angular 2. The circumstance demands a rewrite.
- Uncaught Error: [$injector:modulerr] http://errors.angularjs.org/1.5.8/$injector/modulerr?p0=myApp&p1=Error%3A%2…Bc%20(http%3A%2F%2Flocalhost%3A56663%2FScripts%2Fangular.min.js%3A21%3A179)(…) is the error I get in Google Chrome's console when I try to loop in angular.min.js in a AngularJS 1.5.8 app in Visual Studio 2015. Of course there is no way to Google against this error message which is one of the toughest things about Angular. Wait! That's only if a decorate a div with ng-app="myApp" so I'm probably missing a definition.
- var app = angular.module("myApp", []); ...fixes the problem above and this is perhaps a good cheatsheet
- per the cheatsheet <div ng-app="myApp" ng-controller="myCtrl"> will also loop in a controller and there example is:
app.controller("myCtrl", function ($scope) {
$scope.firstName = "John";
$scope.lastName = "Doe";
});
RUP is Rational Unified Process methodology
This feels like a process halfway between Agile and Waterfall in which there are four phases (Inception, Elaboration, Construction, Transition) making the development technically iterative, but not nearly as minutely so as Scrum. Also there are fixed deadlines to hit (specific dates). Well... why not? There are no Agile purists anymore so who is to say this is bad? Everyone (every business) just does their own thing anyways.
Wednesday, November 2, 2016
ROW_NUMBER in T-SQL is another thing I keep botching in interviews. (twice now)
The interview challenge: How do you return a page of "pagination" more than one page deep in T-SQL results? Well, if it's just the first page, that's easy right? You do something like what follows, to use the Problems table I made here as an example.
SELECT TOP(10) * FROM Problems
WHERE PersonId != 4
ORDER BY ProblemId
But if we want a different "page" ...then what. I had this in my notes, but I suspected it was really expensive (and I still think that) and as a result I found this online which offered:
SELECT * FROM
(
SELECT ROW_NUMBER() OVER ( ORDER BY ProblemId ) AS Spot,
* FROM Problems
WHERE PersonId != 4
) AS WhateverYoudLikeHere
WHERE Spot >= 11 AND Spot <= 20
ORDER BY ProblemId
Tuesday, November 1, 2016
some assorted notes from a set of recent interviews
- You may visit http://www.anapioficeandfire.com/api/books plain as day in a browser, but if you try to slurp the JSON object there down into some jQuery AJAX at an .html page on your desktop that you are just running through Google Chrome you may be in for some heartache. In looking a Fiddler, you see the call consumed successfully and yet the in-page .ajax call falls over to it's error method. Why so? Partway into this is this copy: Regular web pages can use the XMLHttpRequest object to send and receive data from remote servers, but they're limited by the same origin policy. Extensions aren't so limited. An extension can talk to remote servers outside of its origin, as long as it first requests cross-origin permissions. Ah-ha! That has half of the answer for what to do and the rest may be found here, and yes there is a solution. It's not that the thing you are consuming needs to open up CORS permissions, but instead it does actually have something to do with you. Open the command prompt as administrator and navigate to where Chrome lives. On my laptop that is at: C:\Program Files (x86)\Google\Chrome\Application ...then run this command: chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security ...to get a version of Google Chrome with watered-down security. Remember, it worked in Fiddler. It's just Chrome itself that is cantankerous. There is a second step and that is to use async:false/crossDomain:true/dataType:'json' like so:
$.ajax({
url: 'http://www.anapioficeandfire.com/api/books',
type: "GET",
async: false,
crossDomain: true,
dataType: 'json',
success: function(result) { console.log(result); alert('Success'); },
error: function(result) { alert('Failed!'); }
}); - jsbin.com is an interesting place to build and test JavaScript.
- A C# using statement is not taking a try/catch/finally shape in CLR. It has a try/finally vibe. If an exception is thrown in the try part, the finally part still runs (the Dispose method for the IDisposable implementation) but the exception is not caught and "handled." It bubbles right up to you!
- There is a .hasClass in jQuery that goes with the .addClass and .removeClass stuff.
- A gist at GitHub allows for you to save and share a code snippet without dedicating a repository to as much.
- Yes, internal classes may be seen outside of their immediate project in a C# solution by creating a friend relationship between two assemblies.
- The memory leak in Angular's two-way data binding has been significantly improved between version 1.3 and version 1.5.8.
- Try to always use the strictly equals in JavaScript comparisons as the == operator might allow for 6 and "6" to be equal and hence allow for code to blow up downstream.