├── src ├── favicon.png ├── images │ └── kevin_rockon.png ├── pages │ ├── Resume.vue │ ├── Contact.vue │ ├── Training.vue │ ├── README.md │ ├── Consulting.vue │ ├── Categories.vue │ ├── Index.vue │ └── Speaking.vue ├── components │ ├── README.md │ ├── Heading.vue │ ├── Welcome.vue │ ├── Contact.vue │ ├── WelcomeConsulting.vue │ ├── WelcomeTraining.vue │ ├── LatestArticles.vue │ └── SiteHeader.vue ├── layouts │ ├── README.md │ ├── Default.vue │ └── CategoryLayout.vue ├── templates │ ├── README.md │ └── Article.vue ├── styles │ └── global.css └── main.js ├── .gitignore ├── tailwind.config.js ├── static └── README.md ├── todo.md ├── purgecss.config.js ├── README.md ├── blog ├── fix-my-computer.md ├── ASPNET-40-To-ASPNET-Core.md ├── One-Simple-Rule-for-Successful-Consulting.md ├── Enhancing-Your-Applications-For-Windows-7.md ├── Enable-SignalR-Logging-with-One-Simple-Line.md ├── Interview-with-Michael-Rollins-for-HRDevFest-2016.md ├── Simple-HTML-Formatting-in-Sublime-Text.md ├── Wildcard-search-with-LINQ.md ├── Learn-about-Windows-7-Task-Dialogs.md ├── Powershell-How-to-recursively-delete-files-based-of-file-extension.md ├── 50-Ways-to-Avoid-Find-and-Fix-ASP-NET-Performance-Issues.md ├── If-You-Reach-Just-One-Person.md ├── Specifying-Visual-Studio-Version-in-NPM-Installs.md ├── How-to-run-Visual-Studio-Code-from-Zsh-on-Mac-OSX.md ├── Quick-Introduction-to-SignalR-Streaming.md ├── How-to-run-Visual-Studio-Code-from-Terminal-on-Mac-OSX.md ├── My-Defacto-gitignore-file.md ├── Named-Callbacks-in-JavaScript.md ├── swift-kick-show-unbelievable-and-complex-advancements-in-machine-learning-with-ankur-kalra.md ├── Online-vs-Retail-Stores.md ├── No-matter-what-you-do-add-value.md ├── MongoDB-Setting-TTL-on-Documents.md ├── Preloading-Multiple-Audio-Tags-in-Internet-Explorer-9.md ├── Review-7-Recurring-Revenue-Recipes-for-Freelancers.md ├── Console-Games-Why-do-we-have-to-press-start.md ├── Exploring-C-7-0-Out-Variables.md ├── Moving-on-to-Greener-Pastures.md ├── Managing-Your-User-Group-Calendar-Roulette.md ├── The-10-Rule-to-Presentations.md ├── Managing-Your-User-Group-Food.md ├── swift-kick-show-nosql-shouldnt-mean-nosecurity-with-matt-groves.md ├── Running-a-Conference-Like-A-Startup.md ├── A-Diet-Programmers-Can-Relate-To.md ├── My-Attempt-at-LINQ-Pagination.md ├── Leaving-It-Better-Than-You-Found-It.md ├── Building-better-ConnectionStrings-with-ConnectionStringBuilder.md ├── Banks-ATMS-and-Horrible-User-Experiences.md ├── Speaker-Gifts.md ├── Are-we-too-dependent-on-the-Internet.md ├── i-removed-email-from-my-phone.md ├── The-Zen-of-Free-Labor.md ├── Node-js-Using-require-to-load-your-own-files.md ├── Book-Review-Financially-Stupid-People-Are-Everywhere.md ├── about-blog-posts.md ├── Maintaining-SignalR-ConnectionId-rsquo-s-Across-Page-Instances.md ├── Open-Source-Mentality-of-Choosing-Your-Tech-Stack.md ├── How-I-m-Beating-Email-Addiction.md ├── Managing-Your-User-Group-Sponsor-Relationships.md ├── Definition-of-a-Computer-Scientist.md ├── Colossal-Failures.md ├── I-suck-at-writing-unit-tests-but-I-m-trying-to-change.md ├── SignalR-Transports-Explained.md ├── Using-Unity-for-Dependency-Injection-with-SignalR.md ├── What-Makes-A-Good-Bug-Report.md ├── Why-should-ASP-NET-developers-consider-SignalR-for-ALL-projects.md ├── The-Non-Techie-Guide-to-Source-Control.md ├── Anatomy-of-an-XNA-Application.md ├── Non-Tech-Factors-to-Consider-When-Choosing-Your-Tech-Stack.md ├── Review-Everleap.md ├── Shedquarters.md ├── Paying-Attention.md └── Books-I-Read-in-2016.md ├── package.json ├── gridsome.server.js ├── azure-pipelines.yml └── gridsome.config.js /src/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1kevgriff/kevgriffin.v3/master/src/favicon.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | .cache 3 | .DS_Store 4 | src/.temp 5 | node_modules 6 | dist 7 | .env 8 | .env.* 9 | -------------------------------------------------------------------------------- /src/images/kevin_rockon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1kevgriff/kevgriffin.v3/master/src/images/kevin_rockon.png -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | theme: { 3 | extend: {} 4 | }, 5 | variants: {}, 6 | plugins: [] 7 | } 8 | -------------------------------------------------------------------------------- /src/pages/Resume.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /src/components/README.md: -------------------------------------------------------------------------------- 1 | Add components that will be imported to Pages and Layouts to this folder. 2 | Learn more about components here: https://gridsome.org/docs/components/ 3 | 4 | You can delete this file. 5 | -------------------------------------------------------------------------------- /src/components/Heading.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | -------------------------------------------------------------------------------- /static/README.md: -------------------------------------------------------------------------------- 1 | Add static files here. Files in this directory will be copied directly to `dist` folder during build. For example, /static/robots.txt will be located at https://yoursite.com/robots.txt. 2 | 3 | This file should be deleted. -------------------------------------------------------------------------------- /src/pages/Contact.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /src/layouts/README.md: -------------------------------------------------------------------------------- 1 | Layout components are used to wrap pages and templates. Layouts should contain components like headers, footers or sidebars that will be used across the site. 2 | 3 | Learn more about Layouts: https://gridsome.org/docs/layouts/ 4 | 5 | You can delete this file. 6 | -------------------------------------------------------------------------------- /src/pages/Training.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /src/pages/README.md: -------------------------------------------------------------------------------- 1 | Pages are usually used for normal pages or for listing items from a GraphQL collection. 2 | Add .vue files here to create pages. For example **About.vue** will be **site.com/about**. 3 | Learn more about pages: https://gridsome.org/docs/pages/ 4 | 5 | You can delete this file. 6 | -------------------------------------------------------------------------------- /src/templates/README.md: -------------------------------------------------------------------------------- 1 | Templates for **GraphQL collections** should be added here. 2 | To create a template for a collection called `WordPressPost` 3 | create a file named `WordPressPost.vue` in this folder. 4 | 5 | Learn more: https://gridsome.org/docs/templates/ 6 | 7 | You can delete this file. 8 | -------------------------------------------------------------------------------- /src/layouts/Default.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | -------------------------------------------------------------------------------- /src/pages/Consulting.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | -------------------------------------------------------------------------------- /todo.md: -------------------------------------------------------------------------------- 1 | # To Do List 2 | 3 | 1) Home page 4 | 2) Article view 5 | - Disqus 6 | 2) Article list (by Category) 7 | 3) Article list (by Date) 8 | 4) Speaking list (past + upcoming) 9 | 4) Resume 10 | 11 | - Set up Azure Pipeline 12 | 13 | 14 | WHERE I LEFT OFF 15 | 2019-12-05: Working on getting my face on the page. -------------------------------------------------------------------------------- /purgecss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | content: [ 3 | "./src/**/*.vue", 4 | "./src/**/*.js", 5 | "./src/**/*.jsx", 6 | "./src/**/*.html", 7 | "./src/**/*.pug", 8 | "./src/**/*.md", 9 | ], 10 | whitelist: ["svg:not(:root).svg-inline--fa"], 11 | whitelistPatterns: [/^fa-/, /^svg-inline--fa/], 12 | whitelistPatternsChildren: [/^token/, /^pre/, /^code/], 13 | defaultExtractor: content => content.match(/[A-Za-z0-9-_:/]+/g) || [] 14 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Default starter for Gridsome 2 | 3 | This is the project you get when you run `gridsome create new-project`. 4 | 5 | ### 1. Install Gridsome CLI tool if you don't have 6 | 7 | `npm install --global @gridsome/cli` 8 | 9 | ### 2. Create a Gridsome project 10 | 11 | 1. `gridsome create my-gridsome-site` to install default starter 12 | 2. `cd my-gridsome-site` to open the folder 13 | 3. `gridsome develop` to start a local dev server at `http://localhost:8080` 14 | 4. Happy coding 🎉🙌 15 | -------------------------------------------------------------------------------- /src/components/Welcome.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 19 | 20 | -------------------------------------------------------------------------------- /src/styles/global.css: -------------------------------------------------------------------------------- 1 | /* global.css */ 2 | 3 | @tailwind base; 4 | @tailwind components; 5 | /* Add your btn/input/etc components here */ 6 | 7 | @tailwind utilities; 8 | @import url("https://use.typekit.net/wou4pvn.css"); 9 | 10 | .main-heading { 11 | font-family: ff-market-web, sans-serif; 12 | font-weight: 700; 13 | font-style: normal; 14 | font-size: 40pt; 15 | } 16 | 17 | .sub-heading { 18 | font-family: ff-market-web, sans-serif; 19 | font-weight: 700; 20 | font-style: normal; 21 | font-size: 28pt; 22 | @apply w-full; 23 | } -------------------------------------------------------------------------------- /blog/fix-my-computer.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Fix My Computer 3 | permalink: fix-my-computer 4 | date: 2017-05-02 23:30:55 5 | --- 6 | 7 | I get a lot of requests for companies in the Norfolk and Virginia Beach area that fix personal computers. Here are a couple references that I think are looking at. 8 | 9 | > These references come from friends of mine in the industry. I have not vetted any of these companies. Your milage might vary. 10 | 11 | *P&P PC* 12 | 2468 East Little Creek Road, Norfolk VA 23518 13 | (757)-531-3196 14 | [http://www.pandppc.com](http://www.pandppc.com) 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kevgriffincom.v3", 3 | "private": true, 4 | "scripts": { 5 | "build": "gridsome build", 6 | "develop": "gridsome develop", 7 | "explore": "gridsome explore" 8 | }, 9 | "dependencies": { 10 | "@fullhuman/postcss-purgecss": "^1.3.0", 11 | "@gridsome/source-filesystem": "^0.6.2", 12 | "@gridsome/transformer-remark": "^0.4.0", 13 | "gridsome": "^0.7.0", 14 | "gridsome-plugin-remark-shiki": "^0.3.1", 15 | "lodash": "^4.17.15", 16 | "tailwindcss": "^1.1.4", 17 | "vue-disqus": "^3.0.5" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import "./styles/global.css"; 2 | 3 | import VueDisqus from 'vue-disqus'; 4 | 5 | import DefaultLayout from "~/layouts/Default.vue"; 6 | import CategoryLayout from "~/layouts/CategoryLayout.vue"; 7 | import Heading from "~/components/Heading.vue"; 8 | 9 | export default function (Vue, { head }) { 10 | Vue.use(VueDisqus); 11 | 12 | Vue.component('Layout', DefaultLayout); 13 | Vue.component('CategoryLayout', CategoryLayout); 14 | Vue.component('Heading', Heading); 15 | 16 | head.link.push({ 17 | rel: 'stylesheet', 18 | href: 'https://fonts.googleapis.com/css?family=Mali:700|Nunito' 19 | }); 20 | } -------------------------------------------------------------------------------- /blog/ASPNET-40-To-ASPNET-Core.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Upgrading Your ASP.NET 4.0+ Skills to ASP.NET Core' 3 | permalink: asp-net-40-to-asp-net-core 4 | categories: 5 | - ASP.NET Core 6 | updated: '2013-01-24 04:34:48' 7 | date: 2019-04-12 05:00:46 8 | --- 9 | 10 | Have you recently attended one of my talks on "Upgrading Your ASP.NET 4.0+ Skills to ASP.NET Core"? 11 | 12 | I hope you enjoyed it! I would love to chat more about any questions you have! 13 | 14 | [CodeStock 2019 Slides](https://griffcdn.blob.core.windows.net/kevgriffinpublic/asp-net-40-to-asp-net-core/CodeStock%202019%20-%20Upgrading%20Your%20ASPNET%204%20Skills%20to%20ASPNET%20Core.pdf) -------------------------------------------------------------------------------- /gridsome.server.js: -------------------------------------------------------------------------------- 1 | // Server API makes it possible to hook into various parts of Gridsome 2 | // on server-side and add custom data to the GraphQL data layer. 3 | // Learn more: https://gridsome.org/docs/server-api/ 4 | 5 | // Changes here require a server restart. 6 | // To restart press CTRL + C in terminal and run `gridsome develop` 7 | 8 | module.exports = function (api) { 9 | api.loadSource(({ addCollection }) => { 10 | // Use the Data Store API here: https://gridsome.org/docs/data-store-api/ 11 | }) 12 | 13 | api.createPages(({ createPage }) => { 14 | // Use the Pages API here: https://gridsome.org/docs/pages-api/ 15 | }) 16 | } 17 | -------------------------------------------------------------------------------- /blog/One-Simple-Rule-for-Successful-Consulting.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: One Simple Rule for Successful Consulting 3 | permalink: one-simple-rule-for-successful-consulting 4 | categories: 5 | - Business 6 | date: 2014-09-03 00:16:57 7 | --- 8 | 9 | When you're suggesting business decisions for a client, think about it this way: 10 | 11 | > If you were to flip the roles, would you take the advice you are offering? 12 | 13 | Simply put: when I recommend tools, technologies, and other solutions to my clients, I want to always make sure that the suggestion I am providing is something I would do for my own business. 14 | 15 | Do that, and the clients will always keep coming back. -------------------------------------------------------------------------------- /blog/Enhancing-Your-Applications-For-Windows-7.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Enhancing Your Applications For Windows 7 3 | categories: 4 | - Development 5 | permalink: enhancing-your-applications-for-windows-7 6 | date: 2009-11-17 09:36:34 7 | --- 8 | 9 |

I invite you to head over to Developer Fusion, and read my article on "Enhancing Your Applications For Windows 7”.  If you haven’t played with the Windows 7 API Code Pack yet, I definitely recommend it.

http://www.developerfusion.com/article/70531/enhancing-your-applications-for-windows-7/

-------------------------------------------------------------------------------- /blog/Enable-SignalR-Logging-with-One-Simple-Line.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Enable SignalR Logging with One Simple Line 3 | categories: 4 | - "Development - ASP.NET" 5 | permalink: signalr-logging 6 | date: 2015-08-28 23:26:42 7 | --- 8 | 9 | It is easy to think that SignalR works within a black box, but if you are deploying JavaScript clients, here is an EASY trick to learning what is happening underneath the scenes. 10 | 11 | Before you start your connection, add this ONE line of code: 12 | 13 | ```javascript 14 | $.connection.hub.logging = true; 15 | $.connection.hub.start(); 16 | ``` 17 | 18 | Tada! You have logging in your browser console: 19 | 20 | ![](https://griffcdn.blob.core.windows.net/kevgriffinpublic/signalr-logging/logging_preview.png) -------------------------------------------------------------------------------- /blog/Interview-with-Michael-Rollins-for-HRDevFest-2016.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Interview with Michael Rollins for HRDevFest 2016 3 | categories: 4 | - Community, User Groups, and Conferences 5 | permalink: interview-with-michael-rollins-for-hrdevfest-2016 6 | date: 2016-09-01 10:56:33 7 | --- 8 | 9 | Recently, I had the opportunity to sit down with my friend [Michael Rollins](http://www.rollins.io) to talk about life as a mobile SDK developer, drones, and his upcoming HRDevFest keynote on growth through suffering. 10 | 11 | Watch the interview for yourself! Get your tickets for HRDevfest at [http://hrdevfest.org!](http://hrdevfest.org) 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /blog/Simple-HTML-Formatting-in-Sublime-Text.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Simple HTML Formatting in Sublime Text 3 | categories: 4 | - Development 5 | permalink: simple-html-formatting-in-sublime-text 6 | id: 730 7 | updated: '2013-02-27 05:17:35' 8 | date: 2013-02-27 06:00:16 9 | --- 10 | 11 | One common questions I've asked and seen asked quite a bit about Sublime Text is how to quickly and easily format HTML while editing.  There isn't a default key binding for this, but if you select all text and then go to: 12 |
Edit -> Lines -> Reindent
13 | Want to create your own keybinding?  Go to Preferences, Key Bindings - User and add this line: 14 |
{ "keys": ["ctrl+shift+r"], "command": "reindent" , "args": {"single_line": false}}
15 | Enjoy! -------------------------------------------------------------------------------- /blog/Wildcard-search-with-LINQ.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Wildcard search with LINQ 3 | categories: 4 | - "Development - C#" 5 | permalink: wildcard-search-with-linq 6 | date: 2009-04-21 09:17:26 7 | --- 8 | 9 | I just a situation where I needed to perform a wildcard search on a table in my database.  When I used to do ADO.NET, I would simply write my SELECT statements with LIKE keywords to do wildcard searches. 10 | 11 | However, in this project, I'm using LINQ to Entities and the solution didn't work the same way as it did back in SQL land.  My alternative was to use the .Contains() method. 12 | 13 | For example: 14 |
var userList = from u in entity.Users
15 | where u.FirstName.Contains(searchParameter) ||
16 | u.LastName.Contains(searchParameter)
17 | select u;
18 | 19 | Hope this helps if you ever run into this problem. -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | # Node.js 2 | # Build a general Node.js project with npm. 3 | # Add steps that analyze code, save build artifacts, deploy, and more: 4 | # https://docs.microsoft.com/azure/devops/pipelines/languages/javascript 5 | 6 | trigger: 7 | - master 8 | 9 | pool: 10 | vmImage: 'windows-latest' 11 | 12 | steps: 13 | - task: NodeTool@0 14 | inputs: 15 | versionSpec: '12.x' 16 | displayName: 'Install Node.js' 17 | 18 | - script: | 19 | npm install 20 | npm install --global @gridsome/cli 21 | gridsome build 22 | displayName: 'npm install + gridsome cli + gridsome build' 23 | 24 | - task: AzureFileCopy@3 25 | inputs: 26 | SourcePath: 'dist' 27 | azureSubscription: 'Microsoft Azure Sponsorship(c36e07bf-0eab-4330-aa8e-7f95fdcf3319)' 28 | Destination: 'AzureBlob' 29 | storage: 'kevgriffinv3' 30 | ContainerName: 'hosting' 31 | -------------------------------------------------------------------------------- /blog/Learn-about-Windows-7-Task-Dialogs.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Learn about Windows 7 Task Dialogs 3 | categories: 4 | - Development 5 | permalink: learn-about-windows-7-task-dialogs 6 | updated: '2009-12-01 07:00:00' 7 | date: 2009-12-01 07:00:00 8 | --- 9 | 10 |

Please take a few minutes and travel over to DeveloperFusion where my latest article on Windows 7 Task Dialogs has been published.  If you’ve never used a task dialog before, I would definitely recommend them.  I consider them “Message Box 2.0”.

http://www.developerfusion.com/article/71793/smarten-up-your-ui-with-task-dialogs-the-message-box-20/

Let me know what you think!

-------------------------------------------------------------------------------- /src/components/Contact.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 20 | 21 | -------------------------------------------------------------------------------- /blog/Powershell-How-to-recursively-delete-files-based-of-file-extension.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Powershell: How to recursively delete files based of file extension?' 3 | categories: 4 | - Development 5 | permalink: powershell-how-to-recursively-delete-files-based-of-file-extension 6 | updated: '2016-07-15 14:23:38' 7 | date: 2016-07-15 14:15:43 8 | --- 9 | 10 | File this under "took me WAY too long to figure out how to do". 11 | 12 | I just finished doing a Git merge, and ran into an issue where my working folder was polluted with .orig files. 13 | 14 | I wanted to recursively delete all the .orig files. That is apparently harder than it sounds, because it took me 15 minutes to figure out the correct command line. 15 | 16 | So you don't go fumbling like I did: 17 | 18 | ``` 19 | Get-ChildItem . -recurse -include *.orig | remove-item 20 | ``` 21 | 22 | Replace `.` and `*.orig` accordingly. Have fun! -------------------------------------------------------------------------------- /src/components/WelcomeConsulting.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 20 | 21 | -------------------------------------------------------------------------------- /src/components/WelcomeTraining.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 20 | 21 | -------------------------------------------------------------------------------- /blog/50-Ways-to-Avoid-Find-and-Fix-ASP-NET-Performance-Issues.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: '50 Ways to Avoid, Find and Fix ASP.NET Performance Issues' 3 | permalink: 50-ways-to-avoid-find-and-fix-asp-net-performance-issues 4 | categories: 5 | - Self Promotion 6 | updated: '2013-01-24 04:34:48' 7 | date: 2013-01-25 05:00:46 8 | --- 9 | 10 | A couple weeks ago there was a public request on Twitter from the great folks at RedGate to provide tips and tricks for performance in ASP.NET applications.  Come to find out, they selected one of my tips and published it in their ebook "50 Ways to Avoid, Find and Fix ASP.NET Performance Issues". 11 | 12 | It's a free download: http://www.red-gate.com/products/dotnet-development/ants-performance-profiler/entrypage/avoid-find-fix-asp-problems 13 | 14 | Go grab it today! -------------------------------------------------------------------------------- /src/layouts/CategoryLayout.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | -------------------------------------------------------------------------------- /blog/If-You-Reach-Just-One-Person.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: If You Reach Just One Person 3 | categories: 4 | - Deep Thoughts 5 | permalink: if-you-reach-just-one-person 6 | updated: '2010-03-29 06:00:00' 7 | date: 2010-03-29 06:00:00 8 | --- 9 | 10 |

After giving a talk, it’s really difficult to judge if you reached any of the attendee’s.  Normally, you get the occasional “good job” or “thanks, that was a big help.”  Today I got a small mention by Johnathan Bracken, who was sitting in my jQuery From The Ground Up talk at Roanoke Code Camp.  This means a lot, because it shows that my talk stayed in Johnathan’s head past the end of the talk. 

He just started blogging, and mentioned me in his entry I Will Not Run from JavaScript No More. This is very cool to see.  I wish Johnathan the best of luck in his jQuery adventures!  And I expect him to give a jQuery talk at next year’s code camp.

-------------------------------------------------------------------------------- /gridsome.config.js: -------------------------------------------------------------------------------- 1 | // This is where project configuration and plugin options are located. 2 | // Learn more: https://gridsome.org/docs/config 3 | 4 | // Changes here require a server restart. 5 | // To restart press CTRL + C in terminal and run `gridsome develop` 6 | 7 | 8 | const tailwindcss = require("tailwindcss"); 9 | const purgecss = require("@fullhuman/postcss-purgecss"); 10 | 11 | module.exports = { 12 | siteName: 'Kevin W. Griffin', 13 | plugins: [ 14 | { 15 | use: '@gridsome/source-filesystem', 16 | options: { 17 | path: 'blog/*.md', 18 | typeName: 'Article', 19 | route: '/:permalink', 20 | remark: { 21 | plugins: [ 22 | ['gridsome-plugin-remark-shiki', { theme: 'nord', skipInline: false }] 23 | ] 24 | } 25 | } 26 | } 27 | ], 28 | css: { 29 | loaderOptions: { 30 | postcss: { 31 | plugins: [ 32 | tailwindcss, 33 | ...process.env.NODE_ENV === "production" ? [purgecss] : [] 34 | ], 35 | }, 36 | }, 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /blog/Specifying-Visual-Studio-Version-in-NPM-Installs.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Specifying Visual Studio Version in NPM Installs 3 | categories: 4 | - Development 5 | permalink: specifying-visual-studio-version-in-npm-installs 6 | date: 2013-05-14 06:34:08 7 | --- 8 | 9 | Sometimes when you install a NPM package, you'll run into an issue like this: 10 |
C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V110\Microsoft.Cpp.Platform.targets(35,5): error MSB8020: The builds tools for Visual Studio 2010 (Platform Toolset = 'v100') cannot be found. To build using the v100 build tools, either click the Project menu or right-click the solution, and then select "Update VC++ Projects...". Install Visual Studio 2010 to build using the Visual Studio 2010 build tools.
11 | Normally you'll get this if you're only running VS2012 and it wants VS2010/VS2008.  You can ask NPM to use Visual Studio 2012 instead by using with "--msvs_version=2012" command. 12 | 13 | Example: 14 |
npm install socket.io --msvs_version=2012
15 | Tada.  This should work almost every time. -------------------------------------------------------------------------------- /src/pages/Categories.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 16 | { 17 | allArticle { 18 | edges { 19 | node { 20 | id 21 | title 22 | categories 23 | permalink 24 | } 25 | } 26 | } 27 | } 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/pages/Index.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | query Home ($page: Int) { 18 | allArticle (page: $page) { 19 | edges { 20 | node { 21 | id 22 | title 23 | date (format: "MMMM DD, YYYY") 24 | categories 25 | permalink 26 | } 27 | } 28 | } 29 | } 30 | 31 | 32 | -------------------------------------------------------------------------------- /blog/How-to-run-Visual-Studio-Code-from-Zsh-on-Mac-OSX.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: How to run Visual Studio Code from Zsh on Mac OSX 3 | categories: 4 | - Development 5 | permalink: how-to-run-visual-studio-code-from-zsh-on-mac-osx 6 | date: 2015-05-07 13:27:04 7 | --- 8 | 9 | **EDIT:** [You can just do this from Visual Studio Code now.](https://code.visualstudio.com/docs/setup/osx) 10 | 11 | Using [Visual Studio Code](https://code.visualstudio.com) on your Mac, but can't call it from Zsh? 12 | 13 | Using Terminal? [Go here](http://kevgriffin.com/how-to-run-visual-studio-code-from-terminal-on-mac-osx/) 14 | 15 | Currently, there isn't an automatic method for doing this, but with a little code in your `.zshrc` file, you can configure it. 16 | 17 | ``` 18 | function code { 19 | if [[ $# = 0 ]] 20 | then 21 | open -a "Visual Studio Code" 22 | else 23 | local argPath="$1" 24 | [[ $1 = /* ]] && argPath="$1" || argPath="$PWD/${1#./}" 25 | open -a "Visual Studio Code" "$argPath" 26 | fi 27 | } 28 | ``` 29 | Then from Terminal you can type: 30 | 31 | `code` -- opens Visual Studio Code 32 | `code .` -- opens current directory in Visual Studio Code 33 | `code somefile` -- opens somefile in Visual Studio Code -------------------------------------------------------------------------------- /blog/Quick-Introduction-to-SignalR-Streaming.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Quick Introduction to SignalR Streaming 3 | date: 2018-12-13 23:39:46 4 | categories: 5 | - ASP.NET Core 6 | permalink: quick-introduction-to-signalr-streaming 7 | tags: 8 | - asp.net core 9 | - signalr 10 | - websockets 11 | - streaming 12 | - .net core 13 | --- 14 | For my entry this year for [C# Advent](https://crosscuttingconcerns.com/The-Second-Annual-C-Advent), I wanted to do something a little bit different. 15 | 16 | As of late, I've been wanting to start doing several tidbits around cool things that I see in .NET Core and ASP.NET Core. And by the recommendation of my friend, [Brady Gaster](https://twitter.com/bradygaster), I took a look at the new Streaming APIs built into SignalR (for ASP.NET Core). 17 | 18 | And WOW! I'm super impressed with that I saw. 19 | 20 | Check out my video introduction below, and lemme know what you think in the comments! 21 | 22 | 23 | 24 | Source code for this project is available at on [GitHub](https://github.com/swiftkickin/signalr-streaming-v1). -------------------------------------------------------------------------------- /blog/How-to-run-Visual-Studio-Code-from-Terminal-on-Mac-OSX.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: How to run Visual Studio Code from Terminal on Mac OSX 3 | categories: 4 | - Development 5 | permalink: how-to-run-visual-studio-code-from-terminal-on-mac-osx 6 | date: 2015-05-07 13:20:28 7 | --- 8 | 9 | **Edit 06/24/2016:** [You can just do this from Visual Studio Code now.](https://code.visualstudio.com/docs/setup/osx) 10 | 11 | *Edit 12/10/2015: Thanks for commenter on letting know that latest release of Code broke original post. Updated with code from [documentation](https://code.visualstudio.com/Docs/editor/setup).* 12 | 13 | Using [Visual Studio Code](https://code.visualstudio.com) on your Mac, but you want to use it in Terminal? 14 | 15 | Using Zsh? [Go here](http://kevgriffin.com/how-to-run-visual-studio-code-from-zsh-on-mac-osx/) 16 | 17 | Currently, there isn't an automatic method for doing this, but with a little code in your `~/.bash_profile` file, you can configure it. 18 | 19 | ``` 20 | code () { VSCODE_CWD="$PWD" open -n -b "com.microsoft.VSCode" --args $* ;} 21 | ``` 22 | 23 | Then from Terminal you can type: 24 | 25 | `code` -- opens Visual Studio Code 26 | `code .` -- opens current directory in Visual Studio Code 27 | `code somefile` -- opens somefile in Visual Studio Code -------------------------------------------------------------------------------- /src/components/LatestArticles.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 25 | query Home ($page: Int) { 26 | allArticle (page: $page) { 27 | edges { 28 | node { 29 | id 30 | title 31 | date (format: "MMMM DD, YYYY") 32 | categories 33 | permalink 34 | } 35 | } 36 | } 37 | } 38 | 39 | 40 | 45 | 46 | -------------------------------------------------------------------------------- /blog/My-Defacto-gitignore-file.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: My Defacto .gitignore file 3 | categories: 4 | - Development 5 | permalink: base-gitignore 6 | date: 2012-11-12 10:37:23 7 | --- 8 | 9 | Every time I create a new Git repo, I always have to go look for a previous copy of my .gitignore file.  I thought it would be a great idea to just post it up for all to find, in case they were looking for it.  This particular file is built around Visual Studio projects. 10 |
# Ignore file for Visual Studio
11 | 
12 | # use glob syntax
13 | syntax: glob
14 | 
15 | # Ignore Config files with keys and passwords
16 | #ServiceConfiguration*.cscfg
17 | #Web*.config
18 | #App*.config
19 | 
20 | # Ignore Visual Studio files
21 | *.obj
22 | #*.exe
23 | #*.pdb
24 | *.user
25 | *.aps
26 | *.pch
27 | *.vspscc
28 | *.vshost.*
29 | *_i.c
30 | *_p.c
31 | *.ncb
32 | *.suo
33 | *.tlb
34 | *.tlh
35 | *.bak
36 | *.cache
37 | *.ilk
38 | *.log
39 | *.lib
40 | *.sbr
41 | *.scc
42 | *.orig
43 | UpgradeLog*.*
44 | UpgradeReport*.*
45 | [Bb]in
46 | [Dd]ebug*/
47 | obj/
48 | [Rr]elease*/
49 | _ReSharper*/
50 | [Tt]est[Rr]esult*
51 | [Bb]uild[Ll]og.*
52 | *.[Pp]ublish.xml
53 | glob:*.vs10x
54 | *.ReSharper
55 | [Pp]ublish
56 | [Rr]eleaseFiles
57 | [Cc]sx/
58 | [Bb]ackup1/
59 | [Pp]ackages/
60 | 
61 | # Mac Files
62 | .DS_Store
63 | *.DS_Store
64 | ._*
-------------------------------------------------------------------------------- /src/templates/Article.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 23 | 24 | 25 | query Article ($path: String!) { 26 | article (path: $path) { 27 | id 28 | title 29 | date (format: "MMMM DD, YYYY") 30 | categories 31 | permalink 32 | content 33 | } 34 | } 35 | 36 | 37 | -------------------------------------------------------------------------------- /blog/Named-Callbacks-in-JavaScript.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Named Callbacks in JavaScript 3 | categories: 4 | - Development 5 | permalink: named-callbacks-in-javascript 6 | date: 2013-08-06 06:30:49 7 | --- 8 | 9 | You've been taught bad JavaScript for years and years.  What do I mean?  I'm sure you've written code like this more than once in your career: 10 | 11 | ```js 12 | someMethod(function (){ 13 | console.log("doing stuff..."); 14 | }); 15 | ``` 16 | 17 | So what's wrong with that?  It runs and doesn't error.  Heck, even JSLint won't complain about it.  But what happens something goes wrong inside of your callback?  Most debuggers will list the callback as an "anonymous method" in the call stack.  Not very helpful is it?  Isn't there something simple we can do make our callbacks easier to read in a call stack? 18 | 19 | NAME YOUR CALLBACKS. 20 | 21 | Take the example above, and let's name the callback. 22 | 23 | ```js 24 | someMethod(function myCallback(){ 25 | console.log("doing stuff..."); 26 | }); 27 | ``` 28 | 29 | Simple!  Let's imagine doing a jQuery AJAX call with this approach (and yes, I'm ignore the fact that you should use promises -- which are WAY better): 30 | 31 | ```js 32 | $.ajax({ 33 | url: "/myUrl", 34 | success: function onAjaxSuccess (data){ 35 | }, 36 | error: function onAjaxError (error) { 37 | } 38 | }); 39 | ``` 40 | 41 | You're welcome :) 42 | -------------------------------------------------------------------------------- /src/components/SiteHeader.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | -------------------------------------------------------------------------------- /blog/swift-kick-show-unbelievable-and-complex-advancements-in-machine-learning-with-ankur-kalra.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Swift Kick Show - Unbelievable and Complex Advancements in Machine Learning with Ankur Kalra 3 | categories: 4 | - Swift Kick Show 5 | permalink: swift-kick-show-unbelievable-and-complex-advancements-in-machine-learning-with-ankur-kalra 6 | date: 2018-03-14 09:54:52 7 | --- 8 | 9 | On the March 14th episode of the Swift Kick Show, I was joined by my friend Ankur Kalra. I've known Ankur for many years as a member of a private bootstrapped business Slack group. He's been doing some really interesting work with Machine Learning - and I thought he'd be a great guest to have. 10 | 11 | Watch the video below, and check out the [Swift Kick YouTube channel](https://youtube.com/c/swiftkick). Like and subscribe for more great videos! 12 | 13 | ### Unbelievable and Complex Advancements in Machine Learning with Ankur Kalra 14 | 15 | >As a technologist, it's an exciting time to be alive. Recent publications have revealed truly unbelievable results in machine learning, some of which raise interesting and complex ethical questions. In this talk, Ankur will walk through some recent papers that are both technically impressive as well as ethically complex. Though this talk is geared towards people with some minimal technical background, no prior machine learning experience is necessary. 16 | 17 | -------------------------------------------------------------------------------- /blog/Online-vs-Retail-Stores.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Online vs. Retail Stores 3 | categories: 4 | - Deep Thoughts 5 | permalink: online-vs-retail-stores 6 | date: 2010-04-19 06:00:00 7 | --- 8 | 9 | Something amazing happened the other day. 10 | 11 | I wanted to purchase a copy of Splinter Cell: Convinction.  After a little bit of surfing online, I discovered that Walmart had it on sale for $50 (compared to the regular $59.99).  So I drove up to the local Walmart, and walked over to the Video Games section.  Come to discover that the game was $59.99, instead of the $50 I saw online.  Come to discover, the $50 was an “online only price”. 12 | 13 | As any good consumer would do, I pulled out my Android phone and started the Amazon app.  Splinter Cell: Conviction was available for $50, and also eligible for free shipping.  Click… click… and I was finished ordering the game… on my phone… while staring at the game in the cabinet.  So instead of giving Walmart my money, I gave it to Amazon.  I was even willing to pay tax to walk out of the store with it right then and there. 14 | 15 | There are drawbacks to online stores.  I do have to wait several days for my order, and sometimes that’s not acceptable.  However, when you run an online store along side a brick and mortar, you should be trying to compete more with other online retailers.  “Online only” prices are idiotic, and will only convince me to go to another retailer.  If you advertise a price online, I should be able to go to store and pick up the same item for the same price. 16 | 17 | Good job Walmart.  Ask Amazon how they enjoy my money. -------------------------------------------------------------------------------- /blog/No-matter-what-you-do-add-value.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'No matter what you do: add value' 3 | categories: 4 | - Deep Thoughts 5 | permalink: no-matter-what-you-do-add-value 6 | date: 2015-05-14 11:38:29 7 | --- 8 | 9 | Yesterday I had the pleasure of chatting with a gentleman about a potential mentoring gig. The way I like to approach these sort of talks is to determine high level goals. In this case, the client was looking for someone to be a set of expert eyes on a codebase. He is certainly a capable developer, but he's also aware enough to know when he has hit a roadblock. 10 | 11 | We were connected by the work and training I've done with SignalR and ASP.NET, which would prove especially useful in this situation. 12 | 13 | The client discussed the issues he was running into and the thoughts he had around solutions. Normally, this is where you will have the instinct to want to hold off providing guidance. You're the expert. This what people should be paying you for! 14 | 15 | > Always try to add some value. 16 | 17 | That's not how I reacted though. Instead, I spent 10 minute giving my potential-client two or three *free* tips and tricks on what he should explore. Sometimes the simplest tip is all a person needs to push forward. 18 | 19 | The underlying point is that no matter what you do, **always try to add some value**. If my tips bring him to an epiphany, then I have automatically reaffirmed that I am an expert. This could lead to mentoring and other potential work. It could lead to referrals. 20 | 21 | Approach all your interactions as a chance to provide value to someone. It will pay back dividends! -------------------------------------------------------------------------------- /blog/MongoDB-Setting-TTL-on-Documents.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'MongoDB: Setting TTL on Documents' 3 | permalink: mongodb-setting-ttl-on-documents 4 | date: 2014-10-13 14:08:05 5 | categories: 6 | - Development 7 | --- 8 | 9 | On some recent work I was doing with [Winsitter](http://winsitter.com), I needed an approach that would systematically remove documents after a specified period of time within MongoDB. 10 | 11 | Previously, I would have written cron jobs or helpers to clean up the old data. No longer! 12 | 13 | Come to discover, this feature [already exists](http://docs.mongodb.org/manual/tutorial/expire-data/) inside of MongoDB. It is called setting the TTL or Time to Live of a document. 14 | 15 | The process involves creating an index on the date object you'd like to watch. In the example below, I am providing a property on my document called `auditDate`. I want the document associated with that property to automatically remove itself after 5 days or *432000000* miliseconds. 16 | 17 | ``` 18 | dbConnection 19 | .collection("audit") 20 | .ensureIndex({ 21 | "auditDate": 1 22 | }, { 23 | expireAfterSeconds: 432000000 // 5 days 24 | }, function(indexErr) { 25 | if (indexErr) { 26 | console.log("error creating index"); 27 | console.log(indexErr); 28 | } 29 | }); 30 | ``` 31 | 32 | In the example, I'm using the MongoDB node.js library to ensure an index exists. If the index doesn't exist, MongoDB will create it. 33 | 34 | The `expireAfterSeconds` options tells MongoDB that after a specified amount of time, the document should automatically remove itself. 35 | 36 | This quick fix has saved me a ton of time, and I am hoping it saves a ton for you too! -------------------------------------------------------------------------------- /blog/Preloading-Multiple-Audio-Tags-in-Internet-Explorer-9.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Preloading Multiple Audio Tags in Internet Explorer 9 3 | categories: 4 | - Development 5 | permalink: preloading-multiple-audio-tags-in-internet-explorer-9 6 | date: 2012-11-02 06:00:59 7 | --- 8 | 9 | I had a unique problem.  I have an app I'm working on where I needed to preload about 50 audio files for use during the page's lifetime.  If you're up on your HTML5-fu, this is a simple task: 10 | 11 |
12 | <audio id="myAudio" controls preload="auto">
13 |      <source src="/my-podcast.mp3" />
14 |      <source src="/my-podcast.ogg" />
15 | </audio>
16 | 
17 | 18 | In Chrome, this works PERFECTLY (as it should). 19 | 20 | In Internet Explorer, several (if not all) files will fail to preload.  Here's how to figure it: 21 | 22 |
23 | var audioElement = document.getElementById("myAudio");
24 | console.log(audioElement.networkState);
25 | 
26 | 27 | Network state can have 3 options: NETWORK_EMPTY, NETWORK_IDLE, NETWORK_LOADING, NETWORK_NO_SOURCE. 28 | 29 | You "want" it to be IDLE, because that means the file is loaded.  Typically, you'll get NO_SOURCE with Internet Explorer. 30 | 31 | What's a quick fix?  First, make sure there is no preload attribute, and then do this: 32 | 33 |
34 | var audioElement = document.getElementById("myAudio");
35 | audioElement.load(); // kicks off the load
36 | 
37 | 38 | This has worked for me in 100% of the tests I've done tonight.  Feel free to comment on other solutions.  I haven't tested in IE10 yet, so I cannot be certain of how it works. -------------------------------------------------------------------------------- /blog/Review-7-Recurring-Revenue-Recipes-for-Freelancers.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Review: 7 Recurring Revenue Recipes for Freelancers' 3 | permalink: review-7-recurring-revenue-recipes-for-freelancers 4 | categories: 5 | - Reviews 6 | updated: '2015-02-16 09:11:50' 7 | date: 2015-02-16 08:55:19 8 | --- 9 | 10 | During a flight from Norfok to Charlotte, I had the opportunity to read [Ryan Castillo's](https://twitter.com/rmcastil) new book [7 Recurring Revenue Recipes for Freelancers](http://ryancastillo.org/7-recipes-recurring-revenue/). 11 | 12 | In this book, Ryan provides seven actionable sets of guidelines that provides the reader a path way to earning $150k a year. Ryan allows the reader to take a "choose your own adventure" to their career and bottom line. 13 | 14 | This book provides clear ways for readers who are already experienced freelancers or consultants to move their target forward. If you're new to the consulting game, Ryan also provides some great places to get started. 15 | 16 | Ryan's recipe on developing support contracts with new and existing clients definitely struck a cord with me. This is a problem I'm running into now with multiple clients, and I'm going to be able to put Ryan's suggestions into action within the next week. This book has the potential to make me an easy $25k extra each year. 17 | 18 | Many of the recommendations Ryan makes echo throughout the communities I'm involved in daily. Every day, people are putting these recipes into action and are seeing results! 19 | 20 | Ryan is currently [pre-selling his book for $12](http://ryancastillo.org/7-recipes-recurring-revenue/), which is a drop in the bucket compared to what you will make if you put his receipes into adction. -------------------------------------------------------------------------------- /blog/Console-Games-Why-do-we-have-to-press-start.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Console Games: Why do we have to press start?' 3 | permalink: console-games-why-do-we-have-to-press-start 4 | categories: 5 | - "Development - Game Development" 6 | date: 2010-01-05 06:00:00 7 | --- 8 | 9 |

Interesting question came up on Twitter the other day:

“Press Start” screens?  Why can’t I just go straight to the main menu?

If you’re a gamer, especially on consoles, you’ve seen this screen more often than you’d care to.  It’s a little annoyance.  However, there is a very good reason for having this screen in place.

Imagine you’re running four controller on your Xbox, and all four of them are turned on.  Then you put in a single player game, and it comes up to that annoying “Press Start” screen.  Which controller do you use to press start with?  The answer is easy: any of them!

The “Press Start” screen is designed to determine which controller the game should poll for input.  During this screen, the game is polling all connected controllers for input.  If any of them register a “start” button push, the game makes that controller the “default” controller.  The use-case for this scenario is that the player should be able to use any connected controller to play the game, and not be forced to use controller #1.  This is considered a best practice.

The More You Know

-------------------------------------------------------------------------------- /blog/Exploring-C-7-0-Out-Variables.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Exploring C# 7.0: Out Variables" 3 | permalink: exploring-csharp70-out-variables 4 | categories: 5 | - "Development - C#" 6 | date: 2016-11-08 18:41:48 7 | --- 8 | 9 | _In this series, I want to explore a couple of the new C# 7.0 features coming down the pipeline. As with most things, I am working with preview bits, so these features are not guaranteed to work the same way in production._ 10 | 11 | Using the out keyword within C# is nothing new. If you declare a variable within a method called with **out**, you are instructing the compile that you are expecting the method to set the values of those at runtime. 12 | 13 | ```csharp 14 | class Program 15 | { 16 | static void Main(string[] args) 17 | { 18 | string firstName; 19 | string lastName; 20 | 21 | CreateName(out firstName, out lastName); 22 | Console.WriteLine($"Hello {firstName} {lastName}"); 23 | } 24 | 25 | private static void CreateName(out string firstName, out string lastName) 26 | { 27 | firstName = "Kevin"; 28 | lastName = "Griffin"; 29 | } 30 | } 31 | ``` 32 | 33 | Commonly the problem is that you have to declare the variable before the method call using out. In C# 7.0, there is the concept of out variables, which will save you a couple keystrokes by allowing you to declare the variable inline. 34 | 35 | The above example can be quickly refactored: 36 | 37 | ```csharp 38 | class Program 39 | { 40 | static void Main(string[] args) 41 | { 42 | // notice I'm declaring the type INSIDE THE CALL! 43 | CreateName(out string firstName, out string lastName); 44 | Console.WriteLine($"Hello {firstName} {lastName}"); 45 | } 46 | 47 | private static void CreateName(out string firstName, out string lastName) 48 | { 49 | firstName = "Kevin"; 50 | lastName = "Griffin"; 51 | } 52 | } 53 | ``` 54 | -------------------------------------------------------------------------------- /blog/Moving-on-to-Greener-Pastures.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Moving on to Greener Pastures 3 | categories: 4 | - Deep Thoughts 5 | permalink: moving-on-to-greener-pastures 6 | date: 2011-05-25 06:00:00 7 | --- 8 | 9 |

After four years with my current company, Antech Systems, it is time for me to pack up and move on to greener pastures. 

I would like to publically thank Antech for providing me with a foundation to build my career off of.  I came to Antech as a college newbie, recently laid off from Symantec, with no .NET experience of any kind.  Within weeks, I was able to grow into a position where I was not only functional, but able to provide meaningful feedback about the applications being built and the processes use to build them.  Antech was the reason I found the developer community, and was one of the leading reasons why I started the Hampton Roads .NET Users Group.  Without them, I have no idea where I would be right now.

I’m pleased to announce that on June 1st, 2011, I’ll be starting my new position with ComponentOne as a Technical Evangelist. 

In this position, I’ll be working closely with Rich Dudley to help promote ComponentOne in the developer community.  As a Technical Evangelist, it is my goal to help you all in your communities in anyway possible.  Please feel free to use me as a resource.

If you’re going to be in the Kansas City area on June 25th, come out to the Kansas City Developer Conference to see me!  I’ll be talking about MVVM!  If you’re in the area, you should definitely come out.

-------------------------------------------------------------------------------- /blog/Managing-Your-User-Group-Calendar-Roulette.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Managing Your User Group: Calendar Roulette' 3 | permalink: calendar-roulette 4 | categories: 5 | - Community, User Groups, and Conferences 6 | date: 2015-03-06 22:39:16 7 | --- 8 | 9 | One trait of successful user groups is don't play calendar roulette. Meaning: they chose a time or day each month to hold the group meeting. 10 | 11 | > We meet every 2nd Tuesday. 12 | 13 | or 14 | 15 | > We are the last Thursday of the month. 16 | 17 | Why is this important? 18 | ***You want your members to be able to determine meeting dates based off a quick glance of a calendar.*** 19 | Consistency is key. If your meetings are in different venues or different days of the month, you're chancing that someone will forget and not be in attendance. 20 | 21 | **What's a good night for meetings?** 22 | With the Hampton Roads .NET Users Group, I chose the 2nd Tuesday of the month. Why? Because I felt Tuesdays were a better for my schedule. Only once in a 5 year period did I change the meeting. 23 | 24 | My recommendation is to choose a Tuesday, Wednesday, or Thursday. Mondays are bad for folks because it's the first day back to work after a short weekend. Fridays are bad because, dude, it's the weekend. PARTY TIME. 25 | 26 | Be careful with Wednesdays as well. Many church functions occur on Wednesday nights, and that might be limiting a percentage of your population. 27 | 28 | **When is it okay to move the meeting?** 29 | Let's imagine you have a speaker coming into town that's "a big deal". But they're only able to meeting on Wednesday night, and your meetings are Tuesdays. MOVE THE MEETING. Make sure the change is well communicated, and that it's temporary. You might lose attendance that month, but people are adaptable. Just don't make it a habit. 30 | 31 | **Conclusion** 32 | Keep scheduling simple. Hampton Roads .NET members knew where to go and when to be there every month of the year. If you build a level of consistency, you're going to have people showing up out of habit, and that's a recipe for a successful group. 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/pages/Speaking.vue: -------------------------------------------------------------------------------- 1 | 60 | 61 | 64 | 65 | -------------------------------------------------------------------------------- /blog/The-10-Rule-to-Presentations.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: The 10% Rule to Presentations 3 | categories: 4 | - Deep Thoughts 5 | permalink: the-10-rule-to-presentations 6 | date: 2016-03-24 09:18:59 7 | --- 8 | 9 | When mentoring new technical speakers, I like to cite what I call "the 10% rule". 10 | 11 | Think about it like this: If you are presenting on a 100-level topics (for example, "Intro to Angular" or "Building Your First App with Elixir"), you can safely assume that your audience is one of three types people. 12 | 13 | **First**, they are an absolute newbie who is there because they heard about this technology but have practically no experience with it. 14 | 15 | **Second**, they have been to previous talks on the subject or have read a couple tutorials. They are not starting at "ground-zero", but they are darn close. 16 | 17 | **Third**, they are seasoned or beyond 100-level, and they are looking to see if you offer new perspective. 18 | 19 | The 10% rule applies to the first two groups. Your job as the presenter is to try to leave the audience with 10% of the knowledge you have on a subject. 20 | 21 | Ten percent sound like a lot, right? Doesn't have to be. For most developers, this is seeing how pieces lay together or how do you do something from scratch. 22 | 23 | Ten percent might simply be "what problem does the thing I'm showing you solve?" 24 | 25 | My first set of presentations were around jQuery (2007 era). My intro talks discussed manipulating the DOM and listening for events. I'd discuss the "hard" way, but then showed how easy jQuery made it. 26 | 27 | If you're adventuring into 200 or 300-level talks, the same 10% rule can apply. Imagine you want to do a talk on "new C# features". Your expectation is that the audience is familiar with C#. Your 10% is going to be a simple list of what is new, with basic explanations. 28 | 29 | If the attendee goes home and runs into a scenario where a new feature would be useful, you have provided them with the foundation to research more. 30 | 31 | The 10% rule is meant to build foundations for learning. Expose audiences to ideas and concepts, and guide them towards better self-learning. -------------------------------------------------------------------------------- /blog/Managing-Your-User-Group-Food.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Managing Your User Group: Food' 3 | categories: 4 | - Community, User Groups, and Conferences 5 | permalink: user-group-food 6 | date: 2015-10-13 18:45:40 7 | --- 8 | 9 | *Edit: Based off some comments, I've included options for non-lovers of meat. Also added other comments.* 10 | 11 | For a lot of user groups, food depends highly on the sponsor for the month. 12 | 13 | Let's keep this short and sweet: Sponsors. If your instinct is to order pizza for a user group meeting, your attendees already hate you. 14 | 15 | Think about it this way. A lot of people have an opportunity to sponsor a group. You want to be memorable. Pizza is not memorable. 16 | 17 | And you know what else? Sandwiches. This is the new pizza. If you think you're being clever and different by providing Jimmy Johns instead of pizza, your attendees hate you too. 18 | 19 | What could you do instead of pizza? What food would make your company memorable? Here are some ideas: 20 | 21 | **Chipotle** - When I spoke at Richmond .NET in October 2015, MaconIT brought Chiptole burritos. I'm talking about a *box of freakin burritos*. 22 | 23 | **Taco Bar** - Taco bars are fun, and they allow attendees to choose their own mexican adventure. 24 | 25 | **Chick-Fil-A** - Nugget tray. Enough said. 26 | 27 | **PF Changs** - How about some asian flair? Try a mini-buffet of PF Changs favorites. 28 | 29 | **BBQ Buffet** - Pulled pork, beans, coleslaw. Depending on the location, you can get a BBQ buffet for the same price as pizza for a group. 30 | 31 | **Veggie/Vegan Options** - I know, I know. The food above is all mostly of the animal protein category. Please don't forget people that don't eat meat. Salad choices and veggies go a long way. You'd be really surprised how many card-carrying meat eaters will dive into healthy choices. Not sure what Vegan's would eat? Ask one. They'd be more than happy to give you a couple dozen options. 32 | 33 | Don't get me wrong, pizza is awesome. Pizza in EXCESS is horrible (and to be fair, if you brought Chick-Fil-A every meeting -- that would probably get old too). Be good to your groups and don't buy pizza (or sandwiches). Look for creative alternatives. Attendees will love you. -------------------------------------------------------------------------------- /blog/swift-kick-show-nosql-shouldnt-mean-nosecurity-with-matt-groves.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Swift Kick Show - NoSql Shouldn't Mean NoSecurity with Matt Groves 3 | categories: 4 | - Swift Kick Show 5 | permalink: swift-kick-show-nosql-shouldnt-mean-nosecurity-with-matt-groves 6 | date: 2018-04-24 09:54:52 7 | --- 8 | 9 | On the April 18th "Swift Kick Show", I had the opportunity to chat a little bit with my good friend, Matt Groves. However, due to some technical issues Matt was not able to join us live. That doesn't stop the show from going on though! 10 | 11 | Through the power of YouTube and video recording, Matt sat down and did a version of his talk for us to publish. 12 | 13 | Watch the video below, and check out the [Swift Kick YouTube channel](https://youtube.com/c/swiftkick). Like and subscribe for more great videos! 14 | 15 | ### NoSql Shouldn't Mean NoSecurity with Matt Groves 16 | 17 | >As NoSQL databases increase in popularity, they also increase in popularity with hackers. NoSQL databases are vulnerable to traditional attacks like SQL injection (yes, really). Further, the rush to productivity leaves some of these databases insecure-by-design. As a result, ransom notes have plagued databases like MongoDB, ElasticSearch, Hadoop, and CouchDB. This session demonstrates security mistakes and prevention. We’ll also look at what NoSQL vendors are doing to mitigate future attacks. Both devs and devops should come to this session, because the last thing either of you want to see is “SEND 0.2 BTC TO THIS ADDRESS 1zaGVjj9NcyvDLyYpCh33Msq TO RECOVER YOUR DATABASE!” 18 | 19 | **About Matt Groves** 20 | >Matthew D. Groves is a guy who loves to code. It doesn't matter if it's C#, jQuery, or PHP: he'll submit pull requests for anything. He has been coding professionally ever since he wrote a QuickBASIC point-of-sale app for his parent's pizza shop back in the 90s. He currently works as a Developer Advocate for Couchbase. His free time is spent with his family, watching the Reds, and getting involved in the developer community. He is the author of AOP in .NET (published by Manning), and is also a Microsoft MVP. 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /blog/Running-a-Conference-Like-A-Startup.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Running a Conference Like A Startup? 3 | permalink: running-a-conference-like-a-startup 4 | categories: 5 | - Community, User Groups, and Conferences 6 | date: 2014-02-23 21:57:40 7 | --- 8 | 9 | I've worked with a lot of different events. User groups, code camps, MADExpo (I'd link to it, but sadly the site went away a couple months ago), and others. 10 | 11 | They are always the same. *If you build it, they will come.* 12 | 13 | I really don't want that to sound negative, because it's not meant to. The leaders in the community are amazing, and lose a lot of sleep making sure an event is a success. And if it's a free event, they do all that knowing that potentially over 30-50% of the people that promised to attend will skip. 14 | 15 | Heck, even a paid event isn't much better. When we cancelled MADExpo in 2013, I received numerous comments from people saying "Oh, I was looking so forward to MADExpo this year!" That's awesome! Why didn't buy a ticket? 16 | 17 | Since the cancellation of MADExpo, I've been itching to do something new in our area. However, the model of *build it, and they come* didn't seem like it worked anymore. At least, not for a new event. 18 | 19 | By the pressure of my partner-in-crime, [Bret Fisher](http://fishbrains.com), I've been listening through [The Lean Startup](http://www.amazon.com/gp/product/B004J4XGN6/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=B004J4XGN6&linkCode=as2&tag=kevgr-20). The chapter on building a minimum viable product struct a chord with me. Build the absolute minimum to start the learning process of what people want. 20 | 21 | Over the course of two days, I built the minimum viable product for [757DevCon](http://757devcon.com). It's strictly an interest site. I'm throwing out an idea, and you can register for my list if you want to hear more. 22 | 23 | Behind the scenes, I have a series of emails planned out to extract crucial information I need from my potential customers. It's not so much about what they want from a conference, but what are they willing to pay for? 24 | 25 | So what are you waiting for? Go [get on the list](http://757devcon.com), and I'll keep you updated! 26 | 27 | I'd love to hear your questions and thoughts. Post them in the comments below. 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /blog/A-Diet-Programmers-Can-Relate-To.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: A Diet Programmers Can Relate To 3 | permalink: a-diet-programmers-can-relate-to 4 | categories: 5 | - Health 6 | updated: '2009-02-06 06:52:21' 7 | date: 2009-02-06 06:52:21 8 | --- 9 | 10 | Consider this: programmers are typically overweight.  It's our nature.  Ninety-five percent of our job is sitting behind a desk and hacking at a keyboard.  The most movement we get is walking to the bathroom, and going to our car to go to the drive thru. 11 | 12 | About a month ago, I was turned onto the Weight Watchers plan, and it immediately occurred to me that this is the perfect diet plan for developers.  Here is the gist of the plan:  You're allotted x number of points a day.  Points come from the foods and drinks you put into your body.  The number of points you're allowed is based on your gender, weight, height, and activity level. 13 | 14 | The points in a piece of food is determined by the number of calories, total fat, and fiber content of the food.  Anyone that pays to join Weight Watchers is given a calculator for determining the points.  In reality, it's just an equation.  Developers like equations.  We can understand equations.  Here is the equation for Weight Watchers Points: 15 | 16 | POINTS = (Calories / 50) + (Total Fat / 12) - (MIN(Fiber, 4) / 5) 17 | 18 | Ooooh.  That could easily be plugged into a script.  How does this fit into the real world?  My number of points allotted per day is 39.  There is a formula for figuring that out, but I've been unable to find it.  If/when I do, I'll post it here.  But for the record, I'm 6'1, 259 pounds and sit at a desk all day.  If you weigh more than I do, add 1 point per 10 pound increment (260 pounds is technically 40 points).  If you weight less, subtract 1 point per 10 pound increment.  If you are taller than me, add a point or two.  If you're shorter, subtract a point or two.  You should see what I mean. 19 | 20 | Say I go to Burger King, and buy a Whopper with cheese.  That weighs in at 19 pounds (the mayo kills it).  After eating a Whopper, I've already had half my number of points for the day.  Weight Watchers says that's cool, but be careful with your other 20 points.  You still eat what you want, just eat less of it and try to find better alternatives. 21 | 22 | So now you can do the Weight Watchers plan for free.  Use the points equation to do whatever you want.  Lose weight mathematically! -------------------------------------------------------------------------------- /blog/My-Attempt-at-LINQ-Pagination.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: My Attempt at LINQ Pagination 3 | categories: 4 | - "Development - C#" 5 | permalink: my-attempt-at-linq-pagination 6 | date: 2009-10-16 06:00:10 7 | --- 8 | 9 |

Today I’ve been diving into an easy way to paginate record sets in my applications.  Searching around the internet yielded several good walkthroughs on how to do this.  My favorite way came from my friend, Kevin Hazzard, He discussed using the Skip() and Take() extension methods to form fit LINQ into building a SQL statement that’ll do all the heavy lifting for you.

Copying from Kevin’s example, I built the following code snippet:

int pageNumber = 1;
10 | int pageSize = 20;
11 | 
12 | using (var entity = new Entities())
13 | {
14 | 	var recordSet = (from r in entity.SomeTable
15 | 			orderby r.SomeID
16 | 			select r);
17 | 	recordSet = recordSet.Skip((pageNumber - 1) * pageSize).Take(pageSize);
18 | 
19 | 	return recordSet;
20 | }
21 | 22 |

What’s nice about the following code is that since LINQ is lazy loading, the SQL built doesn’t actually execute until we need it too.  The days of returning full datasets are done (yes, we’re still doing that on some projects). 

23 | 24 |

I went the next step to see if I could build an extension method of my own that did all of the above for me automatically.  Here was the result I came up with:

25 | 26 |
public static class ExtensionMethods
27 | {
28 | 	public static IQueryable Paginate(this IQueryable content, int pageNumber, int pageSize)
29 |         {
30 |             return content.Skip((pageNumber - 1)*pageSize).Take(pageSize);
31 |         }
32 | }
33 | 34 |

This extension method takes the query returned from LINQ (an IQueryable), and applies the additional constraints to it.  Here is the first example using my new extension method:

35 | 36 |
int pageNumber = 1;
37 | int pageSize = 20;
38 | 
39 | using (var entity = new Entities())
40 | {
41 | 	var recordSet = (from r in entity.SomeTable
42 | 			orderby r.SomeID
43 | 			select r);
44 | 	recordSet = recordSet.Paginate(pageNumber, pageSize);
45 | 
46 | 	return recordSet;
47 | }
48 | 49 |

 

50 | 51 |

Ta da!  Hopefully that makes sense.  I’m open to other suggestions and comments.  I’m learning that if I take about my thought processes on certain problems, that I receive a ton of great feedback from those who listen.

-------------------------------------------------------------------------------- /blog/Leaving-It-Better-Than-You-Found-It.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Leaving It Better Than You Found It 3 | categories: 4 | - Deep Thoughts 5 | permalink: leaving-it-better-than-you-found-it 6 | date: 2010-01-26 06:00:00 7 | --- 8 | 9 |

When my wife and I bought our house back in April, one of my pet projects has been to renovate the room over our garage.  I knew buying the house that it would be a lot of work, partly because the previous owner didn’t know what he was doing when finishing a room.  I’ve spent the last week and half sanding, mudding, and fixing all the walls in this room.  While sanding some dried mud tonight, I had a thought about how this experience was a lot like building software.

When building software, you’re not sometimes lucky enough to build a system from the ground up.  Normally, you’ll inherit code from developers who have been hacking it for years.  I related this to me working in my room.  I inherited a poorly maintained room.  The joints weren’t level with each other and the mud of the wall wasn’t smooth.  The person doing the work took no pride in the work being done.  The ceiling was also a “hacked” popcorn ceiling.  I say hacked because, instead of using a hopper, the person slung dry wall mud onto the ceiling giving the illusion of popcorn.  The illusion failed though because it looked horrible.

Fast forward to my work in the room last week.  I had to go through and scrap all the excess mud off the wall.  Each wall and joint had to be sanded, and mudded again in order to level everything.  I’ve spend hours of time trying to reverse the effects caused by performing the job incorrectly.

What does this have to do with software development?  Think about when you’re working on a bug in a piece of code, and it’s your first time looking at this code.  How the previous developer left the code is how you’re going to inherit it.  You might have to spend hours undoing the work of the previous person in order to get the code to a state it can be worked with.  Hacks might have to be removed and properly implemented.  Hours will be wasted that didn’t have to be.

When working on new code, do yourself and future developers a favor and leave the code in a state where it can be easily picked up and worked on.  If you’re working on existing code, try to leave it in a better state than it was when you found it.  In the long run, time will be saved, code will be more secure, and a developer will say fewer curse words.

-------------------------------------------------------------------------------- /blog/Building-better-ConnectionStrings-with-ConnectionStringBuilder.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Building better ConnectionStrings with ConnectionStringBuilder 3 | categories: 4 | - "Development - C#" 5 | permalink: building-better-connectionstrings-with-connectionstringbuilder 6 | date: 2011-02-14 05:00:02 7 | --- 8 | 9 | Okay, I never admitted to being a .NET guru or anything, and that’s why I get so excited whenever I run across a gem in the framework that allows me to do something easier and with fewer issues. 10 | 11 | ConnectionStrings has always been one of those things I did the hard way.  For example, I would have a line of code that was like so: 12 | 13 |
14 | string connectionString =  "Data Source={0};Initial Catalog={1};User Id={2};Password={3};";
15 | string.Format(connectionString, serverName, databaseName, userName, password);
16 | 
17 | 18 | This seemed like a logical way to build my connection strings.  However, it wasn’t very flexible.  That was until I discovered the suite of ConnectionStringBuilder classes. 19 | 20 | Let’s take the above OleDb connection string and use the OleDbConnectionStringBuilder to build it. 21 | 22 |
23 | System.Data.OleDb.OleDbConnectionStringBuilder oleDbConnectionStringBuilder  =
24 |             new OleDbConnectionStringBuilder();
25 | oleDbConnectionStringBuilder.DataSource = "myServer";
26 | oleDbConnectionStringBuilder.FileName = "myAccessFile.mdb";
27 | oleDbConnectionStringBuilder.ToString();
28 | 
29 | 30 | Look at how much cleaner that is!  Maybe you’re working with a SQL Server database: 31 | 32 |
33 | System.Data.SqlClient.SqlConnectionStringBuilder connectionStringBuilder =
34 |                 new SqlConnectionStringBuilder();
35 | connectionStringBuilder.DataSource = "myServer";
36 | connectionStringBuilder.InitialCatalog = "databaseName";
37 | connectionStringBuilder.UserID = "userName";
38 | connectionStringBuilder.Password = "password";
39 | connectionStringBuilder.ToString();
40 | 
41 | 42 | Isn’t that awesome?!  Now, finally, let’s imagine you’re doing all this with Entity Framework: 43 | 44 |
45 | System.Data.EntityClient.EntityConnectionStringBuilder entityConnectionStringBuilder =
46 |                 new EntityConnectionStringBuilder();
47 | entityConnectionStringBuilder.ProviderConnectionString = connectionStringBuilder.ToString();
48 | entityConnectionStringBuilder.Metadata = "(entity framework metadata here)";
49 | entityConnectionStringBuilder.ToString();
50 | 
51 | 52 | There you go!  Instead of hand writing your connection strings, take a look to see if there is a StringBuilder class that’ll do the work for you. -------------------------------------------------------------------------------- /blog/Banks-ATMS-and-Horrible-User-Experiences.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Banks, ATMS, and Horrible User Experiences' 3 | permalink: banks-atms-and-horrible-user-experiences 4 | categories: 5 | - Deep Thoughts 6 | updated: '2015-08-20 21:52:06' 7 | date: 2015-08-03 09:18:46 8 | --- 9 | 10 | *Note: I'm pretty much going to rant about a bank experience I had. Lessons aren't obvious, but if you're designing something that's pretty dang important... make sure you have failsafes built-in.* 11 | 12 | I went to my local ATM yesterday to deposit a couple checks. I know, I know... why didn't I just use my phone? Turns out banking phone apps have limits on how much you can deposit through the app and I was well past that limit. ATM was a logical second choice if I didn't want to have to make visit to a teller. 13 | 14 | Generally, this type of visit is quick. 15 | 16 | 1. Pull up to ATM 17 | 2. Insert ATM card 18 | 3. Type in PIN number 19 | 4. Press DEPOSIT, select account. 20 | 5. Insert checks (optical reader will automatically figure out amounts) 21 | 6. Receipt, and on my way! 22 | 23 | Problem started around step 5. I put my checks into the reader where it proceeded to give me a "PROCESSING YOUR DEPOSIT" screen. Normally, this process takes 10 seconds. 24 | 25 | Ten seconds pass... 26 | Then a minute... 27 | OKAY.. five minutes... 28 | 29 | I'm starting to get a bit freaked out because I put a couple good sized checks into a machine and it's not doing anything! 30 | 31 | Next step is to try to call someone. My bank provides a 1-800 number for customer service. Turns out, there is no logical path for "OMG THE ATM STOLE MY CHECKS AND IS FROZEN". And really, there is no path for "I request to speak to a human who can properly direct this call." 32 | 33 | 30 minutes into my freak. I turned two other folks away because ATM was borked. All of a sudden, the screen flashes and pretends like NOTHING HAPPENED AT ALL. "Would you like to deposit the checks?" I pressed the **go** button and the ATM spat my checks out and told me to have a nice day. Wat? 34 | 35 | I also had a decent "check hold" on my account, which is normal when checks are processed. The bank is still investigating what the issue might have been. 36 | 37 | I'm pretty fortunate that I decided to stick around - or else someone might have been able to swipe my checks. Why doesn't the ATM go into "maintenance mode" or something after five minutes of not responding? Thirty minutes is way too long to wait for any sort of respond. 38 | 39 | On another note, why is there physically no way to talk to a human on the phone? At a minimum, I wanted the bank to have an option to "Press 0 if you just need to talk to someone." 40 | 41 | Blah. What horrible user experiences have you had with technology? -------------------------------------------------------------------------------- /blog/Speaker-Gifts.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Speaker Gifts 3 | categories: 4 | - Community, User Groups, and Conferences 5 | permalink: speaker-gifts 6 | date: 2015-01-13 17:47:38 7 | --- 8 | 9 | > This post is a part of a series I wanted to do on simple user group management tips. 10 | 11 | When you visit a user group, the person standing at the computer is most likely not being paid. In fact, a large majority of the technical speaker circuit is filled with unpaid speakers. Not only that, the speaker might incur costs just for having come out. 12 | 13 | **What costs would a speaker have?** 14 | Great question! 15 | 16 | * **Gas** 17 | Let's imagine someone is driving ~4-8 hours round trip to visit a user group. This will include one or two tanks of gas, depending on the type of vehicle you're driving. 18 | * **Hotel** 19 | If I'm driving more than 4 hours in one direction to visit a user group, I probably want to get a hotel for the night. 20 | * **Lost wages** 21 | Odds are if I'm driving to a user group, I need to take the afternoon off work. This means I'm burning PTO or (if you're like me), you're not billing time. 22 | 23 | Organizations like [INETA](http://www.ineta.org) have programs to help offset the costs of for speakers. For example, if I were to travel over 360 miles, INETA will reimburse me $200 for the trip. That's pretty good and covers most of my costs of speaking. 24 | 25 | **How can the user group help?** 26 | I understand that asking you to cover speaker costs is a huge thing. So I'm not going to do that. Still assume that speakers will come of their own freewill and will cover their own costs. 27 | 28 | Consider this: Your goal as a user group leader is to promote the local technology scene. You want to attract people to show up and learn, but you also want to attract great speakers! 29 | 30 | A couple months ago, our user group started a process of giving out speaker gifts. We don't promote it ("HEY EVERYONE! LOOK AT US GIVING A SPEAKER GIFT!"). Instead, the speaker loves the thought behind the gift and keeps us in mind for a return visit in the future. 31 | 32 | These speakers will then talk about you to their speaker friends. "Hey, those guys at the Hampton Roads .NET group are really cool. I definitely recommend getting on their calendar." 33 | 34 | **What kind of gift can we give?** 35 | We just give a $50 Amazon gift card in one of the fancy boxes. That's pretty good, and it's a cost we subsidize with sponsor money. 36 | 37 | A couple months ago, I visited a group called [GANG](http://migang.org) where they gave me a engraved metal mug. That was awesome, and it makes me definitely want to come back. 38 | 39 | Why not start simple and give the speaker a thank you card signed by all the organizers and some of the attendees? Every little bit you can do makes a difference. 40 | -------------------------------------------------------------------------------- /blog/Are-we-too-dependent-on-the-Internet.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Are we too dependent on the Internet? 3 | permalink: are-we-too-dependent-on-the-internet 4 | categories: 5 | - Deep Thoughts 6 | updated: '2010-01-19 06:00:00' 7 | date: 2010-01-19 06:00:00 8 | --- 9 | 10 |

In my office, there lives a monster.  This monster is called “The Internet Killer,” and he likes to poke his head out every now.  When he does, our internet goes down for hours upon hours.  During this time, I still have work too do, but I often find that my production level is limited by the lack of internet.

Are we too dependent on the Internet?

I’m in that weird generation where I have had access to the Internet for most of my life, but I can still remember not having it.  I have used a card catalog.  I have used an encyclopedia.  I have had to retain knowledge for more than a few minutes.

This was also around the time I started learning how to program.  My first few BASIC applications were self taught from a help file.  I didn’t have an Internet to go to whenever I ran into a problem.  I was forced to either figure it out on my own, or travel to the library to reference whatever material (if they had any material at all).  Having to work through these issues forced me to retain knowledge for an extended period of time.  You never knew when you were going to have use what you had learned before.

Fast forward to today.  I’m working on a few features for a project, and we lose our internet.  You might be saying, “Kevin, you should be able to code just fine without the internet.”  And you are right, I should be able to.  However, if you’re venturing into territory that you’re not familiar with, your work is either going to take two or three times as long as it would had you had access to reference materials.

Have you ever heard of books?” Yes, and I have plenty of them.  Books are hard to reference.  Books are awful for troubleshooting problems.  Can you type an error string or code into a book?  How long does it take to find a book that might have the information you’re looking for?  Does it actually contain information that is useful, or just code snippets that is causing the error you have?

Google (Bing, or whatever you use) is fast, accurate (for the most part), and easily accessible.  The “whole world at your fingertips” is no joke.  Within minutes, I have access to references, books, blogs, forums, etc.  Your problem is never new, and the Internet is quick to provide answers.

Does the internet make us stronger, or is it making us weaker?  I’ll let you decide.

-------------------------------------------------------------------------------- /blog/i-removed-email-from-my-phone.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: I Removed Email From My Phone 3 | categories: 4 | - Deep Thoughts 5 | permalink: good-bye-email 6 | date: 2018-05-01 09:54:52 7 | --- 8 | Several years ago, [I wrote about how I was taking steps to reduce my dependence on email](https://kevgriffin.com/beating-email-addiction/). You should go give it a read if you haven't before. 9 | 10 | Like a good diet, I fell off that bandwagon after months and months of doing `really well`. 11 | 12 | Since I own my [own business](https://swiftkick.in), I spend a lot of time in email conversing with clients, employees, contractors, and random people I'm trying to convince to give me money. I organize [conferences](https://revolutionconf.com), [user groups](http://hrnug.org), and a variety of other professional events. I'm active in my church, and get CCed on just about everything. 13 | 14 | I came to the realization that email itself was making me anxious. 15 | 16 | For example, I'd get up in the morning and quickly check email as a part of my morning routine. Some days were fine, but then other days I'd get an email that would **totally ruin me for the entire day.** 17 | 18 | Email became my fidget. If I was standing in line at the store, at a stop light, or just walking towards a building, I'd get my phone out and quickly check my email. 19 | 20 | The absolute worse time to check email is when you physically cannot respond to it. Some emails I forgot about, accidentally archived, or just said "I'll deal with this later". 21 | 22 | Then one day I came to a realization: the email on the phone had to go. 23 | 24 | It was **so easy**. Delete. 25 | 26 | Additionally, I added a message to my email signature specifically stating that I'm returning to my twice-a-day email routine, and I did not carry it on my device. Emergencies needed to move to phone calls or text messages. 27 | 28 | You'd be amazed how quickly an "emergency" dies down when someone has to pick up a phone. 29 | 30 | As of this writing, I've been without email on my device for two weeks. My level of anxiety is pretty much gone. Email takes all of 5-15 minutes depending on what I need to respond to. And best of all, email can only happen when I'm at my laptop - and that is a controlled situation. 31 | 32 | I encourage everyone to take a break from email. Even if it removing notifications or reducing your time to twice daily -- it is amazing how liberating it can be to not need to check email constantly. 33 | 34 | We cannot forget that email is asynchronous. In the same way we'd have to wait for snail mail or carrier pigeon, and email doesn't need to be received or answered immediately. There is no difference between a 2 minute response time and a 12 hour response time. 35 | 36 | I'd love to hear your thoughts about email. Does it rule your life or have you figure out how to tame it for the best? Leave a comment below! -------------------------------------------------------------------------------- /blog/The-Zen-of-Free-Labor.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: The Zen of Free Labor 3 | categories: 4 | - Deep Thoughts 5 | permalink: the-zen-of-free-labor 6 | date: 2009-06-01 04:00:06 7 | --- 8 | 9 | Lets rewind back two years ago.  I was a fresh software developer of our college.  The major problem plaguing college students is that they do not have any practical experience.  How do you obtain practical experience?  You need to work!  You need to make the mistakes you need to make to become a productive professional. 10 | 11 | Out of college, I knew exactly one programming language proficiently: C++.  Proficiently is probably a poor choice of words.  I KNEW C++, but I KNEW enough to make simple decisions and get the job done the best way I could.  My first (technically second, but we won't go into that) professional job was all C#.  I didn't know C#, but I knew enough C++ to become very comfortable with C#.  In fact, one week after starting the job, I was adding new features to the project I was assigned too. 12 | 13 | However, I knew that I needed to expose myself to a several different technologies.  My wife and I took a trip to Nashville and visited with some friends of ours. One night, I was having a discussion with my friend about his hobby, photography.  We had ended up on the topic of him putting up a web page for all of his photos to sell.  I thought it was a wonderful idea, and volunteered to build the site for him.  The caveat was that I would do the site for free, seeing as how I needed to build up my skills in ASP.NET.  He would pay for hosting, etc, and I would build the site for him. 14 | 15 | This was almost two years ago, and the site still remains undone. 16 | 17 | So what happened?  Life happened!  Paying jobs happened!  Of course its a great idea to say that you're going to do something for free to help someone else.  What happens though when you need to mow the yard?  Stay late at work?  Get sick?  Spouse gets sick?  The first thing you drop is the project you're not getting paid for. 18 | 19 | Fast forward to a year ago.  I volunteered to work on my church website.  Same scenario.  I wanted an avenue to build on top of the ASP.NET skills I had, and I figured working on my church website was the best way to do that.  The difference between this project and the first was that I needed the input of several people in order to make any progress on the site.  When you're not being paid, the people you're doing the job for aren't as quick to respond to emails as they would if you were charging per hour for their response.  This site will be done, but it's taken several months longer than it needed too. 20 | 21 | What's the moral of the story?  You need work to show off in order to get more work.  Offer to do a free project every now and then.  Use it for experimenting with new technologies.  Don't allow the project to get too complex.  You don't have time for that.  Get it done as soon as possible.  If you let it go for too much longer, you're never going to complete it.  That is, of course, you have more will power than I do. -------------------------------------------------------------------------------- /blog/Node-js-Using-require-to-load-your-own-files.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Node.js: Using require to load your own files' 3 | categories: 4 | - Development 5 | permalink: node-js-using-require-to-load-your-own-files 6 | date: 2012-12-31 06:00:31 7 | --- 8 | 9 | For a lot of JavaScript developers that are moving over from traditional "browser" development to node.js, they might be casually aware of the require keyword that node.js provides you. 10 | 11 | If you're wondering what I'm talking about, allow me to explain.  In node.js, you can use the node package manager (NPM) to install packages that your application can use.  Express, for example, is a great framework for serving up web applications, and you can grab it via NPM. 12 | 13 | To load Express into your application, you tell node.js that you "require" it be loading into memory. 14 |
var express = require("express");
15 | Node follows a couple rules to find modules.  First, you can ask for a module by name or by folder.  Let's look at Express more closely.  If you were to download Express via NPM, you'd find there is no express.js file in the root directly of the /node_modules/express folder.  However, there is a package.json file that defines the main executable file for express (for fun, go look it up). 16 | 17 | Now, if packages.json doesn't exist or the main executable isn't present, node will resort to looking for your filename with either a .js, .json, or .node extension (unless you've specified). 18 |

Where's this going?

19 | I know, I know... the point. 20 | 21 | Let's say you want to abstract out a piece of your application into another file. 22 |
var userRepository = function (){
23 |    var self = this;
24 |    self.addUser = function (...){
25 |    };
26 |    self.get = function (...){
27 |    }
28 | };
29 | 
30 | module.exports = userRepository;
31 | Add this to a file called userRepository.js. The last line is VERY IMPORTANT! It tells node.js what you'd like to export from this file. This should make more since if you try to use the file. 32 | 33 | In your main.js or wherever you'd like to use userRepository: 34 |
var userRepository = require("userRepository.js");
35 | 
36 | var userRepositoryInstance = new userRepository();
37 | userRepositoryInstance.addUser({...});
38 | userRepositoryInstance.get(...);
39 | Looks simple doesn't it? Pretty much whatever you assign to module.exports will be passed into the variable that calls require(). 40 | 41 | Use this to keep your code clean and uncluttered.  This is only the basics of using require for your own projects, but I think it's a great starting point for developers building their knowledge of node.js.  In the future, I'd like to expand on this topic and show you how you can take this even farther. -------------------------------------------------------------------------------- /blog/Book-Review-Financially-Stupid-People-Are-Everywhere.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Book Review: Financially Stupid People Are Everywhere' 3 | date: 2018-08-03 09:34:31 4 | tags: 5 | categories: 6 | - Reviews 7 | permalink: book-review-financially-stupid-people-are-everywhere 8 | --- 9 | 10 | *For this review, I purchased my own copy of the book on Audible. If you buy your own copy, I would love it if you used one of my links.* 11 | 12 | 13 | 14 | I recently wrapped up reading [*Financially Stupid People Are Everywhere: Don't Be One Of Them*](https://www.amazon.com/Financially-Stupid-People-Are-Everywhere/dp/B01FKUS1WS/ref=as_li_ss_tl?ie=UTF8&qid=1533303623&sr=8-2&keywords=financially+stupid+people+are+everywhere+by+jason+kelly&linkCode=ll1&tag=kevgr-20&linkId=c15f05b1b9668144f20c386321c387e9&language=en_US) by Jason Kelly. It was recommended by one of our guests on [2 Frugal Dudes](https://2frugaldudes.com) and I'm a sucker for books that are recommended to me. 15 | 16 | I decided to consume this book through Audible, because I was close to my credit limit and I wasn't sure when I'd have time to read the book physically. This goes against my ideals that non-fiction should be consumed through phyiscal print and fiction is best enjoyed through Audible. 17 | 18 | FSPAE (yup - abbreviating) gives a pretty opinioned history of why the finanical system is in the current state it is. 19 | 20 | Naturally, I waited too long to write the review after consuming the material - so I'm going to recap the best I can. 21 | 22 | The financial system is poop, and that's caused by normal people who can't do math OR people who can do math but refuse to live below their means due to entitlement. 23 | 24 | That sentence seems pretty harsh - but that's exactly what lead up to the financial crisis in 2008. The icing on the cake is that it's not enough that people were buying into things that they couldn't afford. The problem was companies were actively trying to promote packages to take advantage of people who couldn't do simple math. 25 | 26 | The first third of the people is a lot of berating to bring home the fact the book is called "Financially Stupid People...". 27 | 28 | The rest of the book goes pretty deep into financial influence into government, almost to the point of conspiracy theory. We can go back through several Presidential administrations and see that key members have lineages that tie back to powerful banks and financial institutions. 29 | 30 | Overall, FSPAE is an quick read but not actionable in any way. I don't believe that actionable advice was the target of the book though. If you're looking for a quick listen or would like a little more history on how we got into the financial mess we're in, give *Financially Stupid People Are Everywhere: Don't Be One Of Them* a read. 31 | 32 | -------------------------------------------------------------------------------- /blog/about-blog-posts.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: About Blog Posts 3 | date: 2017-05-03 12:50:43 4 | permalink: about-blog-posts 5 | categories: 6 | - Deep Thoughts 7 | --- 8 | After overhauling my personal site, I learned that I dislike the term `blog`. Instead, I want to be more professional by writing `articles`. 9 | 10 | I just recently spent a couple days overhauling my personal site - or as I used to call it, my blog. 11 | 12 | That term `blog`... 13 | 14 | I've been `blogging` for about ten years, and I made several observations about what I actually put into my `blog`. 15 | 16 | > It's all basically BS, sprinkled with content of value. 17 | 18 | And I see this on a lot of `blogs`. The content is very "point in time" - meaning that it is only relevent within a couple days of the post going out. 19 | 20 | For me, these posts included things like "I'm speaking at XYZ conference" or "Here are my slides for ABC event". 21 | 22 | ## What is a better term? 23 | Articles. 24 | 25 | I trimmed a lot of fat from my `blog`. And instead of calling the posts that got to stay `blog posts`, I'm adapting the term `article`. 26 | 27 | This approach is designed to fix several issues with my site. 28 | 29 | **First**, the content needs to be evergreen-ish. My post about speaking at a code camp in 2010 isn't evergreen. Heck, it wasn't green at all. A hundred people might have read that post and never looked back. Why even publish it? 30 | 31 | Where is a better place for that type of "in the moment" posts? Twitter! Facebook! LinkedIn! Social media (or micro-blogging as it used to be call) is perfect for these types of posts. 32 | 33 | **Second**, the content needs to be more commanding. As a professional, it is more meaningful for me to say "I wrote an article about this topic, go give it a read." instead of "oh, I blogged about that a couple months ago". 34 | 35 | Folks are more likely to share a great article they read versus a blog post they came upon. 36 | 37 | **Third**, there is no need to be a "regular" blogger. The articles I publish have dates on them (see the bottom of this page), but you don't really have any idea what the latest post is. 38 | 39 | By the way, I am looking at adding a "recent articles" section to the sidebar. So I'll probably invalidate my previous statement. 40 | 41 | ## Where do the "micro" posts go? 42 | This is a good point to talk about? Where should the "micro" posts go? Obviously, it's a good idea for me to continue promoting activities I'm involved in. But if the content doesn't fit into the category of "article", where does it go? 43 | 44 | I've set up a separate area of the site for speaking engagement, past and future. This is great for an at-a-glance view of what I'm up to, and also allow people to gauge whether I'm worth inviting to their own events. (Psss, I'd love to speak at your event. Just ask!) 45 | 46 | But this is a good place for social media. Twitter, mostly. But Facebook and LinkedIn are good locales as well. These places are meant to be short lived. Nobody actively goes back through your timeline looking for what you said three years ago (unless you're Donald Trump). 47 | 48 | ## Conclusions 49 | I don't want to knock anyone that maintains a `blog`. I'm not that type of person, so it's not something I want to do. 50 | 51 | I want my content to be more focused and helpful. I feel really guilty when I don't post on a regular basis. Blogs give that illusion. It's "dead" if you're not posting every week. With my new format of "articles", I don't have that guilt. 52 | 53 | What are your thoughts? Am I overthinking it? Am I right on point? I'd LOVE to hear your thoughts in the comments below. -------------------------------------------------------------------------------- /blog/Maintaining-SignalR-ConnectionId-rsquo-s-Across-Page-Instances.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Maintaining SignalR ConnectionId’s Across Page Instances 3 | categories: 4 | - Development 5 | permalink: maintaining-signalr-connectionids-across-page-instances 6 | date: 2012-02-15 10:00:52 7 | --- 8 | 9 |  2/28/2013 - With the 1.0 release of SignalR, I can't guarantee the solution below will work the same.  The big problem with this solution is that ConnectionIds are reused across tabs and browser windows since it's cookie based.  You might not have the results you're expecting.  The SignalR team doesn't recommend this action, and I can agree.  I didn't see it when I wrote the post.  This is a decent guide for overriding the connection id factory, so I'll leave it up for archival purposes. 10 | 11 | I’m a huge fan of SignalR, and today I was looking at a particular problem.  I would think it’s more of a feature, but in certain use cases it can be considered a bug. 12 | 13 | When you start a connection to SignalR for the first time, you are assigned a ConnectionId.  SignalR uses this to determine what messages should go to you, and allows the server to direct messaging at a particular user. 14 | 15 | If you were to refresh the page, SignalR will assign you a NEW ConnectionId.  This could be good or bad… but if you’re trying to maintain some sense of state between your clients and the hub, it’s bad. 16 | 17 | So I looked into how to make SignalR reuse ConnectionIds in the case of a page refresh.  There are really two steps involved. 18 |

1) Set a cookie on the client

19 | When you start() a new connection, SignalR will return a ConnectionId.  You’ll want to set a cookie with that ConnectionId in it. 20 |
    $.connection.hub.start().done(function () {
21 |         alert("Connected!");
22 |         var myClientId = $.connection.hub.id;
23 |         setCookie("srconnectionid", myClientId);
24 |     });
25 | 
26 |     function setCookie(cName, value, exdays) {
27 |         var exdate = new Date();
28 |         exdate.setDate(exdate.getDate() + exdays);
29 |         var c_value = escape(value) + ((exdays == null) ? "" : "; expires=" + exdate.toUTCString());
30 |         document.cookie = cName + "=" + c_value;
31 |     }
32 | As you can see, this gets the ConnectionId from the hub connection and stores it in a cookie. 33 | 34 | 2) Use your own IConnectionIdFactory 35 | 36 | This might be scary territory for you, but it’s actually pretty simple.  We want to create our own version of the IConnectionIdFactory interface for SignalR to use. 37 |
    public class MyConnectionFactory : IConnectionIdFactory
38 |     {
39 |         public string CreateConnectionId(IRequest request)
40 |         {
41 |             if (request.Cookies["srconnectionid"] != null)
42 |             {
43 |                 return request.Cookies["srconnectionid"];
44 |             }
45 | 
46 |             return Guid.NewGuid().ToString();
47 |         }
48 |     }
49 | This does two things.  First, it’ll check your cookie for a ConnectionId it should use.  If it exists, we’ll simply return that ConnectionId and all will be good in the world. 50 | 51 | If the cookie does NOT exist, we need to generate one.  By default, SignalR uses a GUID, so we’ll just repeat that functionality.  You can use any value you want, but make sure it’s unique. 52 | 53 | Don’t forget to wire it up!  Add this to you Global.asax file under Application_Start(). 54 |
AspNetHost.DependencyResolver.Register(typeof(IConnectionIdFactory), () => new MyConnectionFactory());
55 | And you’re all set!  SignalR will now use your new ConnectionIdFactory to generate or reuse ConnectionIds. 56 | 57 | Enjoy! -------------------------------------------------------------------------------- /blog/Open-Source-Mentality-of-Choosing-Your-Tech-Stack.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Open Source Mentality of Choosing Your Tech Stack 3 | categories: 4 | - Deep Thoughts 5 | permalink: open-source-mentality-of-choosing-your-tech-stack 6 | date: 2016-07-04 16:06:21 7 | --- 8 | 9 | When I initially wrote *Non-Tech Factors to Consider When Choosing Your Tech Stack*, I left out one important conversation point: Open Source. 10 | 11 | [Steve and Carol](http://kevgriffin.com/non-tech-factors-to-consider-when-choosing-your-tech-stack/#comment-2671492103) got me in the comments. 12 | 13 | ###How should Open Source affect your decision to choose a tech stack? 14 | 15 | In a previous life, I used to work for a component vendor. Our company built, sold, and supported a variety of components that saved developers time. I had the opportunity to meet thousands of awesome developers who do the hard work every day in the trenches. 16 | 17 | I always questioned why people bought our stuff. The internet at the time was already full of dozens of comparable or better components which were open sourced. Buying our components seemed like an extreme waste of resources. 18 | 19 | That was until I understood the value-cost of SUPPORT. One of our customer was a large financial firm who bought hundreds of developer licenses to a library. This library wasn't anything special - but any of those developers could instantly request technical support from the project manager for the library. (Normal people would have to go through traditional support means, but still had good service.) 20 | 21 | Imagine same company, same team - they decide to use a popular component that is 100% open source. Same team runs into a technical hurdle: either a flaw in the component, or a flaw in the developer's understanding of the component. 22 | 23 | Where does a developer go in this case? Google? Stack-overflow? Github issues? 24 | 25 | A common phrase amongst open source maintainers is "we accept pull requests". I used to believe this was mean-spirited, but you have to understand that folks that manage an open source project have lives and other concerns then your bug. Roll up your sleeves and dive in. 26 | 27 | ###You didn't answer the question: How should Open Source affect your decision to choose a tech stack? 28 | 29 | In the soft-factors article, I discussed that some developer-types just are not suited to work with new technology. Same goes for open source. 30 | 31 | If a developer or team is not comfortable getting their hands dirty in public code, there is NO WAY they should integrate open source software. Don't expect a maintainer to bend over backwards to solve your problem or push you in the right direction. Some do -- but many don't have the bandwidth for that. 32 | 33 | There are some exceptions to this though. Consider massive open source projects such as jQuery, Angular, React, and the .NET Framework. These products are open source and accept pull requests, but they are backed by large organizations who have a vested interest in keeping the projects up and running. You cannot pick up a phone and dial support, but you can file an issue and a team of developers will take you seriously. 34 | 35 | ###You are not alone 36 | The general developer community is amazing. There are thousands and thousands of developers out there that will at least attempt to push you in the right direction if you hit a snag in an open source project. 37 | 38 | I love open source software, and I greatly take for granted the hard work many people have put into my favorite projects. 39 | 40 | Open Source software isn't going away either. The movement is going to grow larger than it is today, and if you are not on the bandwagon as at least an observer, it is going to leave you behind. 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /blog/How-I-m-Beating-Email-Addiction.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: How I'm Beating Email Addiction 3 | categories: 4 | - Deep Thoughts 5 | permalink: beating-email-addiction 6 | date: 2015-05-21 09:54:52 7 | --- 8 | 9 | Today, I really want to talk about email, because I see people everywhere having the same issue with email that I had. I used to be REALLY addicted to email. When I use to wake up in the morning, first thing I would do is check my email on the phone. After sitting at my desk, I would open my email tab and leave it up all day. At night, I would habitually pull out my phone to see if a new email came in. 10 | 11 | It was like I was a drug addict always needing a fix. I couldn't do it anymore. 12 | 13 | One day, I was watching a video and the gent talking said something that kicked off my intervention. 14 | 15 | >Your email is someone elses TODO list for you. 16 | 17 | Holy crap. That hits home. But think about it! Our email serves a couple purposes: 18 | 19 | **Informational**. Reservations reminders, events coming up, someone's address or phone number. These emails have a purpose, but it's not necessary that you act on them immediately. This email totally falls into that category. Gmail categories these under Social, Forums, and Updates. 20 | 21 | **Request followup**. Let's say you ask someone to provide some information. "Hey Kevin, here is the powerpoint you asked for." Remember, if you sent the request for something, you've injected a TODO into someone's list. 22 | 23 | **Promotional**. People try to sell you stuff, but legitimate. Amazon does this a lot. "Hey Kevin, noticed you were looking at chainsaws. Here's a great list of popular ones online." 24 | 25 | **Spam**. It's meat, in a can. 26 | 27 | Email is also asynchronous. That means when I send an email, it can get a response within five minutes or 5 months. It's safe to send some emails and close the tab! It's also a false expectation of others to think you're going to respond to an email within a few minutes. 28 | 29 | I want to share a couple tips for how I broke my email addiction: 30 | 31 | ##I turned off email notifications on my phone 32 | This is groundbreaking! I was so programmed to look at my phone whenever it beeeped, it was maddening. The phone could even be on the other side of the house, and that beep would cause me to stop what I was doing and hike to get it. For what? A statement from the cell phone company. Not worth it. 33 | 34 | This also had the side effect of increasing battery life of my phone. Since it wasn't consistently checking for email, I was getting more battery life. Did you know if don't touch a phone all day, it'll only use like 5% of it's battery? 35 | 36 | ##I limited email time to twice a day 37 | In the morning, I put together a todo list for the day. Part of that is checking email. Since email is a todo list from others, it makes sense for me to look at my email, determine what needs to be responded to, and add it to my list. Some email will be immediate responses. Why add them to the list if all I need to respond with "yes" or "no"? 38 | 39 | Next, I'll check email towards the end of the day. Any email I sent in the AM might be responded too, unless they read this. It also gives me a chance to look at my todo list, and send emails that needed to be sent. It also prevents me from doing off the cuff emails that I would later not have sent. 40 | 41 | ##Inbox zero should be a goal, not a requirement 42 | A lot of folks talk about empty inboxes, and I agree to a point. I believe all emails that you need to follow up with some be archived off and added to your TODO list. My Todo program Todoist has an add-on that allows me to add emails to my todo list. 43 | 44 | Sometimes you might just want to keep an email front and center. That's okay! But anything that isn't important should hit the trash or the archive. -------------------------------------------------------------------------------- /blog/Managing-Your-User-Group-Sponsor-Relationships.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Managing Your User Group: Sponsor Relationships' 3 | permalink: user-group-sponsor-relationship 4 | categories: 5 | - Community, User Groups, and Conferences 6 | date: 2015-01-26 11:58:38 7 | --- 8 | 9 | As a user group leader, you might have this feeling that you need to get sponsors for your user group. **This is a common feeling!** 10 | 11 | In fact, it's one of the most common questions I get as the Director of Membership for INETA. I've seen groups that bend over backwards for sponsors, such as providing attendee lists (with contact information) or letting them do 15 minute sponsors presentations. Over marketing is a huge turn off for attendees, and has potential to limit the growth of your group. 12 | 13 | > For purposes of this discussion, a sponsor is a recruiter, headhunter, placement firm, etc. Pretty much anyone that wants to hire your talent pool. 14 | 15 | > Yes, venues are sponsors. Vendors are sponsors. But that's a different dynamic. The majority of user group "sponsors" are going to be companies looking to place workers. 16 | 17 | I want to offer you a different perspective before you go out and solicit for user group sponsors: 18 | 19 | **What do you offer?** 20 | 1. Access to a community of professionals interested and dedicated to a particular technology. 21 | 2. An environment specialized for engagement and learning. 22 | 3. Mailing lists (maybe) 23 | 4. Discussion boards (maybe) 24 | 25 | Over all, you have a supply of **talent**. Nevermind the skill ranges, but you have a group of folks who are 10% higher than anyone else on the market. Why? Because they're showing up. That's worth gold and more to the right employer. 26 | 27 | **What do they offer?** 28 | 1. Pizza money 29 | 2. Access to a hidden community of professionals they've placed in positions across the region. 30 | 31 | I'm going to call #2 a farce and this is *totally based on my experience.* I've had many sponsors (recruiters) say "We'll send the word out to our people and see if we can get out to the group." But the people don't come. 32 | 33 | So that leaves #1. Food. Drinks. Substance of some kind. 34 | 35 | **How does this empower you?** 36 | THEY need you more than YOU need them. Let's look at a worse case scenario: *you have no sponsors for food*. 37 | 38 | ***Oh well.*** 39 | 40 | When I started my first user group back in 2009, I was scared silly that people wouldn't show up because there was no free food. Put it this way: if someone is coming only for free food, you don't want them at your group anyway. 41 | 42 | I begged for sponsors. "Please please please bring us free food." 43 | 44 | Later, I started getting competition for sponsorships. These companies know what you have, and they WANT to be involved. Use this to your advantage. For us, it meant paying for the right to sponsor a meeting. Twelve meetings per year, that's something worth monetizing. 45 | 46 | Take that last paragraph with a grain of salt. It's a real *first world problem*. Smaller groups might not want to pull that card, and that's okay. But don't bend over backwards for sponsors. 47 | 48 | >THEY need you more than YOU need them. 49 | 50 | **How can I supplement not having a sponsor?** 51 | Donations? A lot of smaller groups throw out a hat for pizza money, and people put money into it! 52 | 53 | Try a shorter meeting without food? 54 | 55 | Create a post-meeting outing that everyone is invited to. At our group, we started a tradition of going to a local diner for pie. Get creative! 56 | 57 | **Wrapping up** 58 | Running a user group is hard. Your thoughts on priorities might be out of line with what they really should be. Some of the best user groups I've been to have started in IHOPs or as meetings at a Starbucks. 59 | 60 | You don't need sponsors. You *want* sponsors. And you hold the high card in this game. 61 | -------------------------------------------------------------------------------- /blog/Definition-of-a-Computer-Scientist.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Definition of a Computer Scientist 3 | permalink: definition-of-a-computer-scientist 4 | categories: 5 | - Deep Thoughts 6 | date: 2009-03-04 15:26:24 7 | --- 8 | 9 | What is a computer scientist?  Google gives the definition: a scientist who specializes in the theory of computation and the design of computers.  In most of our minds, a computer scientist is a person that builds computer systems.  More recognizable names (at least in terms of what a person with a computer science degree would be hired for) for a computer scientist would be developer, coder, software engineer, or software architect.  A lot of people will argue with me that computer scientist is more than just a coder, and I would fully agree.  Although, when a person wants to be a software developer, they are forced most of the time into a computer science program, as it's the best way for they to obtain the skills required to build large software systems. 10 | 11 | But the definition is besides the point.  The real point of this post is to comment on a conversation retold to me by a colleague who's taking a senior-level college course.  To put the conversation into perspective, I need to describe the course (and for the record, I have taken this course myself several years ago).  This course is a project management course for wannabe computer scientists.  In the first semester of the class, students are required to come up with "problems" and probable solutions to them.  The problem and solution are then pitched to a panel of industry professionals.  The solution is actually implemented within the second semester.  As you might think, developing a problem from within thin air is quite daunting.  Eventually though, students discover a problem that obtains approval from the professor. 12 | 13 | This conversation spawned due to my colleague's group not being able to find a problem.  As far as I was told, several problems were proposed and spot down.  When a particular idea was shot down, the professor said, "Your job as computer scientists is to  innovate." 14 | 15 | This statement is just *wrong*.  Your job as a computer scientist is not to innovate!  Your job as a computer scientist is to SOLVE PROBLEMS.  Now, it is possible for a problem to be solved in an innovative manner, but you should never innovate for the sake of innovation.  In the real world (definition: the world outside of academia), you will be given problems to solve, and you will be expected to solve them.  Furthermore, you will be given your problems, not expected to discover them on your own.  Creating your own problems to solve would make you an entrepreneur, not a computer scientist (which you would be when you actually solved the problem). 16 | 17 | For example, let's say I have a glass window and at 5:00 everyday the sun shines through, displaying a terrible glare on my computer screen.  An innovative solution to the problem would be to design a microfilm composite that reduced the glare depending on the amount of sunlight shining through.  Another solution would be to buy a set of blinds.  Not "innovative" by any means, but it solved the problem. 18 | 19 | What advice do I have for the group of computer science student trying to get through this project?  Don't try to come up with a brand new problem.  That's impractical, or the solution to the problem is to high of a level for you to understand as an undergraduate.  Instead, try to take an existing problem with bad solution.  I guess you could say you should take a bad solution and *innovate*?  Ideally, you just want to get through the semester.  When you enter the "real world", the problems will come to you.  At least these problems will be paid, and you won't have to worry while worrying about an English midterm, linear algebra homework, and your seventeenth algorithms assignment. 20 | 21 | Finally, take everything your professor says with a grain of salt.  They probably haven't seen the real world in a long time. -------------------------------------------------------------------------------- /blog/Colossal-Failures.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Colossal Failures 3 | categories: 4 | - Deep Thoughts 5 | permalink: colossal-failures 6 | date: 2010-03-02 06:00:00 7 | --- 8 | 9 | One of my favorite television shows is Mythbusters.  It’s not that I’m enthralled with the myths themselves, but the engineering required prove the myths correct or incorrect (“Confirmed” or "Busted!”). 10 | 11 | Recently, I ran across a session by Adam Savage talking about Colossal Failures.  Here is the video if you have an hour to kill (really the first 30 minutes is all you need to listen to), or just skip ahead. 12 | 13 | 14 | 15 | (If you can't see the video above, please view in your browser and not in an RSS reader) 16 | 17 | This video is inspiring for me.  Adam talks about two instances where he took on a task where he bit off more than he could chew.  First, he talked about having to build a baseball throwing machine for department store display.  The store was under tight restrictions, and gave Adam less than a week to design, build, and implement this system.  Adam didn’t succeed due to dozens of unforeseen issues. 18 | 19 | Second, Adam talked about having to build a set complete with a talking ATM.  He ran into tons of issues, and didn’t have anything done for the first day of filming.  He was asked to go home, and then several days later was asked to come back to get a verbal flogging from the crew. 20 | 21 | What does this mean to us? 22 | 23 | Failing is a method of learning.  Failing is a bit of a subjective term.  If you've made a mistake, you’ve failed.  Some failures are easier to rebound from than others.  However, failures are worth it if you learn something from them. 24 | 25 | Adam learned that while he does good work by himself, the common trait of both his examples was that he didn’t ask for help.  Some jobs are too large for a single person to take on by themselves.  Keep a good network around you of people you trust and respect.  These people can be lifelines in the most frustrating times of a project.  Don’t have a network?  Look for a community event in your area. 26 | 27 | How have I failed? 28 | 29 | I’ve walked into several situations where I had no idea what I was doing.  Being a younger developer, I don’t have the experience as someone with 10 or 15 years experience.  In my current shop, most projects are on the shoulders of one or two developers.  With any project that has come across my path, I’ve picked them up and ran with them the best I could.  As Adam said, I was “making it up as I went.”  I made several poor decisions that seemed good at the time.  When I discovered they were bad decisions, I took immediate steps to fix them.  Never leave a bad decision for someone else to clean up.  Step up and accept them, and then proceed to make it right.  Adam talked about providing money back to his customers.  He accepted his failures, and wanted to take steps to make it right (even if it meant giving up part of his pay). 30 | 31 | Preventing Failures 32 | 33 | Keep a support structure.  Join a user group or visit a code camp.  Keep learning.  Surround yourself with people smarter than you.  Listen to their advice (but take all advice with a grain of salt).  One person will sometimes succeed, while a team will never fail. -------------------------------------------------------------------------------- /blog/I-suck-at-writing-unit-tests-but-I-m-trying-to-change.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'I suck at writing unit tests, but I''m trying to change' 3 | permalink: i-suck-at-writing-unit-tests 4 | categories: 5 | - Deep Thoughts 6 | date: 2015-02-26 22:25:55 7 | --- 8 | 9 | *65 tests* 10 | 11 | I have just hit a personal record when it comes to writing unit tests. A measly 65 unit tests. I've always noticed that there are three types of developers: those that never test, those that are pragmatic about testing, and then those that say TEST ALL THE THINGS. 12 | 13 | Most of my career has been in the first camp. I never tested my code. That's what QA departments were for. The team would write a feature, and ship it off for testing. Most of the times it would get a thumbs up, or it would get rejected because if you held the 'T' key while jumping up and down and patting your head, the computer would explode. 14 | 15 | >... those who are out there doing "Unit Testing 101" talks really suck at them. 16 | 17 | *68 tests* 18 | 19 | Within the past five years, I've grown to really appreciate the **WHY** you should unit test - but the **HOW** had left me in stitches. And let's be honest about it: those who are out there doing "Unit Testing 101" talks really suck at them. Not that the material is bad, but the concepts are too simplified. 20 | 21 | *Today, we're going to create unit tests for our calculator service. If I Add 5 and 5, I should get 10. Yay green!* 22 | 23 | *Today, we're going to create unit tests for our bowling score tracker. If I bowl a strike, but then a 7, I should get a 17 in the first frame.* 24 | 25 | No no no. I live in a world where I talk to external dependencies like databases, web services, etc. In .NET land, that's why you start learning about great things like Dependency Injection. *"Oh Kevin, your tests shouldn't talk to a database. Instead, you should have an interface for talking to a datasource and then write a mock implementation of that."* But.. but.. my applications talks to a database. 26 | 27 | I worked on a small project where I wrote a bunch of tests based around mocks only to determine that I wasn't testing any of the freakin' code. My fake code was tested fabulously! 28 | 29 | *72 tests* 30 | 31 | **Seeing the light** 32 | I had this amazing revelation during a 7 hour car ride with my friend, [Kendall Miller](https://twitter.com/kendallmiller). In a nutshell, he said, "We just stand up the database." Mind. Blown. Imagine this concept: being able to stage your entire application in a couple seconds. Not only are you testing that you're able to insert or update records, but you're continuously testing if your database creation scripts are up to date. 33 | 34 | **It's all baby steps** 35 | For a new client, I have pushed myself really hard to make sure that most aspects of the business and data layers have testing around them. All new features get a series of tests. This is well before I start implementation in the UI. As a result, I'm gradually ensuring that my application works the way that I expect it too. 36 | 37 | A lot of code is written to support the tests. For example, between each test I want to wipe the database clean and start with good data. I am testing a "unit", aren't I? No two tests are dependent on each other. 38 | 39 | **Keep on moving** 40 | I feel really good about this code. There isn't anymore of this ridiculous writing of fake implementations. I'm finding that with every test I write, I'm learning something new. If you find yourself in a similar place as me: wanting to write tests, but it has always seemed too impractical or too complex, I want to offer you some advice. 41 | 42 | Just do it. Write one test. Is the code you want to test too complicated or too involved? That is a great excuse to break it up and refactor. Find someone who really knows or really enjoys writing tests and ASK them for feedback and guidance. They might hurt your feelings, but that's okay. Don't forget why you're doing this! Your code will get better. Your code will stay better. Practice makes perfect! 43 | 44 | Now get out there and write some tests! 45 | -------------------------------------------------------------------------------- /blog/SignalR-Transports-Explained.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: SignalR Transports Explained 3 | categories: 4 | - Development - ASP.NET 5 | permalink: signalr-transports-explained 6 | date: 2015-08-17 21:52:00 7 | --- 8 | 9 | When I sit down to talk to people about SignalR, a common discussion we have is around transports and what the difference between them are. While SignalR gives you the flexibility to choose your own transport, it is often a better bet to simply allow the library to choose for you. 10 | 11 | ## How does SignalR determine which transport to use? 12 | 13 | There are two pieces of the puzzle that need to be evaluated before a transport is chosen. The **client** and the **server**. Keep in mind, a SignalR client can be something other than JavaScript.. and the server can be something not running on IIS. 14 | 15 | If you [head over to SignalR documentation](http://www.asp.net/signalr/overview/getting-started/introduction-to-signalr#transports), they provide a really great overview on how SignalR chooses a transport. 16 | 17 | A simple way to explain the process is this: 18 | 19 | 1. If you're using legacy browser (IE8 or later.. *cough*)... use Long Polling. 20 | 2. Do you need JSONP support? Yes? Long polling, for you. 21 | 3. Okay okay. Let's try Websockets! This works well IF: 22 | * You're not doing JSONP 23 | * You're not going cross-domain 24 | * You ARE going cross-domain AND client supports CORS (Cross-Origin Resource Sharing). 25 | * Client supports WebSockets **(IE10+, Chrome, Firefox, Safari, etc)** 26 | * Server supports WebSockets **(IIS 8.0+ or self-hosted SignalR)** 27 | 4. No WebSockets? Sorry. Give Server Sent Events a try (most likely on non-IE browsers). 28 | 5. No SSE? Try Forever Frame (IE browsers). 29 | 6. No FF? MORE LONG POLLING! 30 | 31 | ## What are the pros and cons of each transport type? 32 | Excellent question! Let's walk through the list worse-case to best-case. 33 | 34 | ### Long Polling 35 | Long polling is a game of hurry up and wait. During this process, you are opening up a pipe (AJAX call) for the server to use for possible future communication. Anytime the server needs to send a message, the existing connection can be used. 36 | 37 | However, when a connection is used, the connection is closed. In order to continue communicating with the server, a client will need to reestablish the connection. In a best case scenario, the server is continuously sending data, so a connection is always reestablishing. Worse case, the connection stands open for up to two minutes (default timeout on most browsers). The process of continuously opening and closing connections can be a bit of a strain on the server. 38 | 39 | Long polling works well on old browsers, including some browsers which should have died ten years ago. This is the final fallback position if no other acceptable transport can be used. 40 | 41 | ### Forever Frame 42 | Warning: Forever Frame (FF) is Internet Explorer only, but it's really interesting how this process works. When a connection is established with FF, a hidden Iframe is created on the page. However, the page loaded into the Iframe is special. The connection will never closed. 43 | 44 | Since the connection remains open forever, the server can use it to continuously send new script. These scripts are loaded and executed on the parent page. 45 | 46 | Any client to server communication needs to be done the traditional way, via AJAX calls. 47 | 48 | ### Server Sent Events 49 | Some technologies stand the test of time, and Server Sent Events (SSE) is a great example. SSE is a server to client communication protocol developed in the Netscape days. It creates an object called an EventSource, which is a pipe from the server to the client. Anytime the server needs to send data, the EventSource pipe can be used. 50 | 51 | SSE is supported on all browsers, except Internet Explorer (sorry, but you have Forever Frame). Just as Forever Frame, if the client needs to communicate back with the server, a traditional AJAX call will need to be made. 52 | 53 | ### WebSockets 54 | Holy. Grail. Seriously. There is nothing better than WebSockets. When a WebSocket connection is made, there is a one-to-one connection between the client and server. Both are capable of communicating on the existing pipe. 55 | 56 | Of course, you are technically limited by the browser and server being used for a connection. Internet Explorer 9 and older need not apply (IE10+ are the only versions with WebSockets support). Firefox, Chrome, and Safari generally have no problems. 57 | 58 | For .NET folks deploying to IIS, you better be sure you are using IIS version 8 (or greater). IIS7 did not have support for WebSockets. 59 | 60 | ## Pulling It All Together 61 | As you look at the various transports available, you should start to appreciate what SignalR is doing for you underneath the scenes. What would happen if you had to implement all these different scenarios yourself? -------------------------------------------------------------------------------- /blog/Using-Unity-for-Dependency-Injection-with-SignalR.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Using Unity for Dependency Injection with SignalR 3 | categories: 4 | - "Development - ASP.NET" 5 | permalink: using-unity-for-dependency-injection-with-signalr 6 | date: 2013-01-08 06:00:31 7 | --- 8 | 9 | I've had bit of a day, and a large part of it was learning how to wrangle SignalR into using my dependency injection provider (in this case, being Unity).  There are a couple thoughts, that I'd like to communicate to you all in case you're looking to do the same thing.  Also, if you have suggestions on what I could do differently, I'm more than open to hearing.  This is solution that worked for me, and I'm hoping it'll work for you. 10 | 11 | NOTE: This is built using SignalR v1.0-RC, which is a Prerelease NuGet package.  I'll try to update if this changes after release. 12 | 13 | First, what do we want to do? 14 |
public class MyHub : Hub
15 | {
16 |    public MyHub(ISomeInterface interface)
17 |    {
18 |       // handle constructor injection here
19 |    }
20 | }
21 | There's a hub, but it doesn't have a default constructor.  I'd like to be able to have SignalR automatically INJECT the constructor requirements when we load a new instance of the Hub. 22 | 23 | There are TWO things we need to do.  First, we need to build our container (with Unity) and tell SignalR to use it. 24 |
        public static void Initialise() // this isn't my misspelling, it's in the Unity.MVC NuGet package.
25 |         {
26 |             var container = BuildUnityContainer();
27 | 
28 |             var unityDependencyResolver = new UnityDependencyResolver(container);
29 | 
30 |             // used for MVC
31 |             DependencyResolver.SetResolver(unityDependencyResolver);
32 |             // used for WebAPI
33 |             GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
34 |             // used for SignalR
35 |             GlobalHost.DependencyResolver = new SignalRUnityDependencyResolver(container);
36 |         }
37 | 
38 |         private static IUnityContainer BuildUnityContainer()
39 |         {
40 |             var container = new UnityContainer();
41 | 
42 |             // register all your dependencies here.
43 |             container.RegisterType<ISomeInterface, SomeInterface>();
44 | 
45 |             return container;
46 |         }
47 | Simple enough. You might want to know what SignalRUnityDependencyResolver looks like: 48 |
public class SignalRUnityDependencyResolver : DefaultDependencyResolver
49 |     {
50 |         private IUnityContainer _container;
51 | 
52 |         public SignalRUnityDependencyResolver(IUnityContainer container)
53 |         {
54 |             _container = container;
55 |         }
56 | 
57 |         public override object GetService(Type serviceType)
58 |         {
59 |             if (_container.IsRegistered(serviceType)) return _container.Resolve(serviceType);
60 |             else return base.GetService(serviceType);
61 |         }
62 | 
63 |         public override IEnumerable<object> GetServices(Type serviceType)
64 |         {
65 |             if (_container.IsRegistered(serviceType)) return _container.ResolveAll(serviceType);
66 |             else return base.GetServices(serviceType);
67 |         }
68 | 
69 |     }
70 | What's going on here? We're creating a new SignalR dependency resolver, and inheriting from the default dependency resolver that SignalR uses. When SignalR goes to resolve a dependency, we're first going to ask Unity if it has an existing implementation. If it does not, we pass the request on to SignalR to get its default (if one is available). 71 | 72 | Why do we have do this? First, you can just replace the IoC container altogether, but I have had no luck registering all the various types that SignalR uses. This was by far an easier approach. 73 | 74 | You'd like to think everything will just work now, right? Wrong. The dependencies in your hub still will not injected. My understanding is that this is by design, so here's how to work with it. 75 |
private static IUnityContainer BuildUnityContainer()
76 |         {
77 |             var container = new UnityContainer();
78 | 
79 |             container.RegisterType<ISomeInterface, SomeInterface>();
80 |             container.RegisterType<MyHub>(new InjectionFactory(CreateMyHub));
81 | 
82 |             return container;
83 |         }
84 | 
85 |         private static object CreateMyHub(IUnityContainer p)
86 |         {
87 |             var myHub= new MyHub(p.Resolve<ISomeInterface>());
88 | 
89 |             return myHub;
90 |         }
91 | This should be simple to follow. I'm registering a new type: MyHub, and telling Unity how to create a new instance of it. Creating it involves resolving the interface myself, and creating the new instance. This instance gets routed through SignalR and eventually executed. 92 | 93 | I'm also a user of StructureMap and Ninject, and I need to sit down to figure out this same process with those frameworks (if I even need to).  If you already have experience with them, let me know what you did. -------------------------------------------------------------------------------- /blog/What-Makes-A-Good-Bug-Report.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: What Makes A Good Bug Report? 3 | categories: 4 | - Development 5 | permalink: what-makes-a-good-bug-report 6 | id: 618 7 | updated: '2009-09-23 06:00:39' 8 | date: 2009-09-23 06:00:39 9 | --- 10 | 11 | As developers, we understand one fundamental truth: our software is going to break.  It's not a matter of if, it's a matter of when.  Hopefully on your team, you have a dedicated testing staff.  Other teams are not quite as lucky.  Their testers might be the project manager, or a single person who's responsible for testing all software produced by your company. 12 | 13 | Developers are terrible at testing their own software.  I'm my own worst tester, and that's because I have a large understanding of how it works.  Without trying, I can make the software work flawlessly each and every time.  On my teams, I state that I want others using my code as much as possible.  But what happens if something breaks? 14 | 15 | Hopefully your company employs a bug track of some sort.  For example, my company uses FogBugz for all of our bug tracking.  However, not many people in my company understand how to write a useful bug report.  My goal is to outline some of the minor things that can be done to make a bug report more helpful to the developer who's going to be using it. 16 |

1. Use descriptive titles

17 | Whenever I see a bug with a title like "Got an error in (name a section of the app)", I die a little inside.  I also see bug titles every day where it's just the name of the section of the app, for example "Order Screen" or "Customer Profile".  Imagine you're a developer who's going through a bug list.  I tend to put these bugs off until later because in order to figure out what I need to do, I have to open the bug. 18 | 19 | Instead, let's try for bug titles like this: "Error 'unable to save user information' when on the user profile screen".  I know what the error is, and where it is.  That's helpful!  Or "Order Confirmation: Clicking OK doesn't respond".  Again, very helpful.  As the developer, I don't have to guess what the problem is. 20 |

2. Steps to reproduce

21 | For the past few weeks, we've had this intermittent problem when saving a user's profile.  Every single time it's occurred, I'm nowhere near the tester.  I've been unable to reproduce it.  Every time it happens, I ask "what was the input?" and I'm constantly answered with "I don't know".  Without a details list of steps for reproducing the bug, I cannot guarantee that I'll be able to fix the bug.  When using guideline #3, you can save a lot of time. 22 |

3. Screen shots, screen shots, screen shots

23 | A picture is worth a 1,000 words.  If you're having trouble verbalizing what the problem is, take a screen shot.  Please make sure that a screen shot is worthwhile though.  If you're working on a web application, and it renders correctly in Firefox, but not in IE, take a screen shot!  If you've filled out a 15 field form, and it errors out, take a screen shot!  When used in combination with guideline #2, you don't have to write out all the information typed into the form. 24 |

4. Prioritize correctly

25 | When you're adding a bug to the system, take into consideration how important fixing the bug is to the current or next release.  If there is a misspelled word, I wouldn't classify it as a "MUST FIX!".  Instead, you should be giving it a lower priority, such as a "Medium" or "When there is time".  If the system is unable to process customer orders, which is the sole reason for using the system, then you might want to mark that as a "MUST FIX!". 26 | 27 | This guideline is subjective though.  The person in charge of the next release, a project manager or lead developer, should have final say over what priority a bug is. 28 |

5. Expectations

29 | If the system did something you didn't quite expect to happen, let the developer know.  In many cases, whatever happened was the product working as designed.  This is a perfect opportunity to discuss flow of application.  One person's design might not make sense to someone else. 30 | 31 | For example, if the app allows you to hand type in dates, but only in the DD/MM/YYYY format and you typed in MM/DD/YYYY format, the system will fail.  That's not exactly a bug, because the system is set up to only accept dates in a certain format, but it is a bug in terms that the system didn't do what you expected. 32 |

6. One Issue Per Bug Report

33 | I can understand how tedious it must be to create a bug report.  Seriously, what is it?  Two, maybe three clicks?  When creating a bug report, make sure you're only referencing one issue.  That way individual issues can be prioritized and worked on solely by themselves.  Verification can be done on a single issue, and not a group.  When you list multiple items in a bug, you're risking that one item might be missed.  Additionally, if I'm the developer on the bug, I can't close it out until all items in the bug have been satisfied.  I might be able to fix all but one item, and the bug will remain in the tracker until I have time or resources to fix it.  If the bugs were individual, I could close out all the fixed issues and they could be evaluated again. 34 | 35 |
When writing your next bug report, please take these guidelines into account and make it easier on your developers. 36 | 37 | I welcome any question or comments!  What do you think?  Anything you would add to the list?  Remove?  Let me know in the comments! -------------------------------------------------------------------------------- /blog/Why-should-ASP-NET-developers-consider-SignalR-for-ALL-projects.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Why should ASP.NET developers consider SignalR for ALL projects? 3 | categories: 4 | - "Development - ASP.NET" 5 | permalink: why-should-asp-net-developers-consider-signalr-for-all-projects 6 | date: 2012-07-09 07:00:07 7 | --- 8 | 9 | The concept of the “static” web went away a long time ago.  When web developers started looking towards jQuery to build “ajax” web applications, we hit a wall where an instance of a page was a dynamic object to be manipulated. 10 | 11 | This turned even more when the first HTML5 specs came down the line, and we were introduced to WebSockets.  An amazing idea: a client application being able to connect directly to a server for communication purposes.  I’ve said it before: software development works in a circle.  If you’ve ever written a client-server application, you know what I mean.  In my 9th grade computer science class, I wrote a version of Battleship that used Berkley sockets to communicate peer to peer with a computer over the network.  Fourteen years later, I’m doing the same thing again but on the web. 12 | 13 | The problem we face when dealing with technologies like WebSockets is that it’s not universally supported across all browser and server stacks.  If we focus on .NET developers, the majority of us are running web applications on IIS version 6 or 7.  WebSockets are only officially supported on IIS version 8. 14 | 15 | If your users are using IE6-9, you’re also at a loss.  Internet Explorer 10 is the only Microsoft browser to support WebSockets out of the box.  Chrome, Firefox, Safari, and Opera users don’t need to worry – they’re covered. 16 | 17 | So if we can’t have WebSockets, can we still have a rich peer to peer communication stack like WebSockets? YES. 18 | 19 | There are various ways to implement solutions.  For example, a long time ago I used to implement ‘Interval Polling’ on my applications.  On a standard interval, say 60 seconds, I would go to the server and request new data.  If the server has data to return, that was the time to do it.  If not, the cycles are wasted.  Obviously, this is a huge bandwidth drain and the overhead of each call is cumbersome. 20 | 21 | Other solutions include long polling, which is the same as interval polling, except the request remains open until the server decides to return data or until the connection times out.  Then there is Server Sent Events, which don’t even ask me about.  I understand it’s based off some old Netscape technology, but that’s about it. 22 | 23 | There are a lot of solutions.  Some only work on newer browsers.  It’s a chore: how do you support multiple clients without tons of code rewrite? 24 | 25 | The answer my friends, is SignalR 26 | 27 | SignalR is a framework for building asynchronous applications.  For web developers, that means I can build applications that break the request->response cycle of the web and move to more of a one-on-one connection that old client server architectures used to offer. 28 | 29 | The mistake a lot of developers make is assuming that SignalR is strictly for web.  That’s incorrect.  For you server infrastructure, ASP.NET is the most common way to building your applications.  However, you can also self host SignalR and also host using the OWIN standard. 30 | 31 | As far as clients are concerned, JavaScript is the main way.  In fact, when I demo SignalR it’s 100% all JavaScript.  I do make a point of touching on the fact that SignalR is also support in Silverlight, Windows Phone, iOS, OSX, and even in regular ol’ C#.  If you have a single server implementation, you can use multiple clients to connect to it. 32 | 33 | Ok, Griff.  This must complicated to code, right? 34 | 35 | I would be a bad blogger if I just left you hanging.  Here’s my 5 minute SignalR demo for you: 36 | 37 | [tube]http://www.youtube.com/watch?v=tEBaDo_sFfA[/tube] 38 | 39 | The video does a really good job of showing you all the steps.  There are two parts to a basic SignalR application.  First is the server side, which we build a construct called a Hub.  Think of a Hub as a central location for all connections for your application. 40 | 41 | Like code?  Here is ALL the C# I write to implement a server-side function: 42 |
public class ChatHub : SignalR.Hubs.Hub
43 |     {
44 |         public void BroadcastMessage(string message)
45 |         {
46 |             // rebroadcast the message to all the connected clients
47 |             Clients.writeMessage(message);
48 |         }
49 |     }
50 | The most confusing thing here might be this mysterious Clients object.  The Clients object is dynamic, meaning you can set properties or call methods on it that might not really exist physically.  SignalR will take all those calls and translate them into messages that are sent to each client currently connected to the hub. 51 | 52 | Here’s a look at the code over on the client: 53 |
<script type="text/javascript" src="~/Scripts/jquery.signalR-0.5.2.js"></script>
54 |     <script type="text/javascript" src="SignalR/Hubs"></script>
55 |     <script type="text/javascript">
56 |         $(document).ready(function () {
57 |             var chat = $.connection.chatHub;
58 |             chat.writeMessage = function (msg) {
59 |                 $("#messages").append("<li>" + msg + "</li>");
60 |             }
61 | 
62 |             $("#buttonSubmit").click(function () {
63 |                 chat.broadcastMessage($("#txtInput").val());
64 |             });
65 | 
66 |             $.connection.hub.start();
67 |         });
68 |     </script>
69 | The request to the SignalR JavaScript file is straight forward, but then there is this magical request to SignalR/Hubs that you might be wondering about.  This file is dynamically generated by SignalR.  It gives your page all the information it needs to talk back to any Hubs you might have created.  Because of this, I can use the object $.connection.chatHub and JavaScript doesn’t throw a fit.  It’s a real object! 70 | 71 | I use the chatHub object in two different ways.  First, I create a new function off of it called writeMessage.  This is called from the server.  WAT?  Yes!  If you look at the hub code above, I’m calling Clients.writeMessage and the client has a method called writeMessage! 72 | 73 | Just below that is a call to chat.broadcastMessage.  Look back at the hub, the method broadcastMessage is defined!  The circle of life is complete. 74 | 75 | Ok.  LASTLY, there is this call to $.connection.hub.start()This method kicks off the transport negotiation between your server and client.  Websockets?  Long pollings?  Blah blah blah.  You can override all this stuff, but just let SignalR do what it does best. 76 | 77 | And there you have it! 78 | 79 | SignalR is extremely easy to use, and I’m definitely recommending it as a replacement for 90% of the .NET AJAX work I’m seeing done in the community.  Take a couple minutes, download the package via NuGet and try it out for yourself.  You won’t be disappointed. 80 | 81 | Feel free to ask any questions, and hit me up on the Twitters @1kevgriff. -------------------------------------------------------------------------------- /blog/The-Non-Techie-Guide-to-Source-Control.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: The Non-Techie Guide to Source Control 3 | permalink: the-non-techie-guide-to-source-control 4 | categories: 5 | - Deep Thoughts 6 | date: 2014-10-30 16:45:19 7 | --- 8 | 9 | _Update 1: Brandon pointed out a mistake in my math. Adjusted to reflect his comments._ 10 | 11 | This is one of those posts that I have been meaning to write for a long time. 12 | 13 | As a consultant, I often find myself in a situation where I need to introduce a client to the concept of source control and why it is important for the long term success of the project. This post is meant to serve that purpose for a long time going forward, and also to help anyone else that might have a need in the future. 14 | 15 | > For technology friends: please use this post. Please suggest changes. Let's make it better for everyone! 16 | 17 | ##The Problem I'm Seeing 18 | Recently, I walked onto a project where I was asked to review some source code and see if I could suggest some changes. I had complete access to the original developer, so I asked her if it would be possible for me to get access to source control. 19 | 20 | Ten minutes later, I received a FTP address with username and password. I could have easily taken down the whole system with a keystroke! Hundred of man hours would have gone down the drain! 21 | 22 | This is **NOT** acceptable. Protection is easy and low cost. 23 | 24 | ##What is source control? 25 | This should be an easy one. Source control is a mechanism that allows a development team to track individual changes of files in a project over time. 26 | 27 | Have you ever used "Change Tracking" feature inside a Microsoft Word file? As you type, Word will track what you write, what you delete, and other assorted changes that you make. You are able to comment on each change, and later accept or reject them. 28 | 29 | Source control works the same. As you work on a project that probably contains tens to hundreds of files, the source control system manages what is happening. You can audit the changes, and even rollback changes if they are not acceptable. 30 | 31 | ##Why source control? 32 | There are several great reasons why you want to implement source control into your project. 33 | 34 | ### It prevents against hardware and software malfunction 35 | 36 | Sometimes hard drives go bad. I have lost count of the number of systems I have walked into where the company stored all their code on a server with no protection. 37 | 38 | How many man hours of time have gone into the production code that is running your business? The largest team I have worked on as a professional was about 6-9 people. The project had been in existence for about 10 years. Let us say that one member of the team contributed 2000 hours a year to the project (40 hours per week times 52 weeks, and then adjust for vacation and sick time). 39 | 40 | 2000 man hours * 6 employees = 12,000 man hours 41 | 12,000 man hours * 10 years = 120,000 man hours 42 | 120,000 man hours = 60 man years 43 | 44 | Average salary of a software developer = $75,000 per year (can vary, but bear with me) 45 | 46 | Total replacement cost of software = $75,000 * 13.9 years = **$4,500,000** 47 | 48 | That is a lot of math to do, but the result is realistic. If you bought a car worth 1 million dollars, do you think you would leave it out in the snow, wind, and rain? Why are you leaving the code that runs your business unprotected on hard drives whose chance of failure goes up daily. 49 | 50 | ### It prevents human error 51 | 52 | Developers are human. We make mistakes. 53 | 54 | Once I was called by a developer to help assist with an issue in a web application he was prototyping. The issue he was having was complicated, and seemingly happened *by accident*. His project had no source control, which means that there was no way to determine *what* he did. Even worse, there was no easy way to know *how to fix it*. 55 | 56 | Luckily in his situation, we were able to figure out the problem and correct it. This was after wasting 3 man hours of time on a problem that could have been solved within 10 minutes. 57 | 58 | Source control would have told the young developer what he changed, and provide a simple way to undo the changes. 59 | 60 | ### It allows safe experimentation 61 | 62 | When your software is built like a house of cards, you are less likely to want to make sweeping changes. 63 | 64 | What if we spend 40 hours and build "feature X" which our customers would love? Lets say that 13 hours into the development we discover that a critical bug is preventing users from paying with their credit cards. What do you do? 65 | 66 | Option one is undo all 13 hours of work we've invested, fix the issue, and push it out live again. 67 | 68 | Option two is to fix the issue, and push it live with the half-done "feature X". 69 | 70 | Option three is to postpone implementing the fix until "feature X" is completed. 71 | 72 | Option four, if you had source control, is to stash the changes to "feature X" and fix your issue. Later, you can come back to "feature X" and pick up where you left off. 73 | 74 | Source control gives you the ability to make changes without worrying about the stability of your software. Fix issues as they pop up, but keep pressing forward on new, exciting features! 75 | 76 | ## But We Have Backups 77 | Awesome! You should definitely have backups. Disaster recovery is a real problem, and I hope you never have to use it. 78 | 79 | Imagine my customer from earlier. They had backups. If I took down the system, they could call their hosting provider and ask to restore from backups. 80 | 81 | How long do you think this process would take? Minutes? Hours? _DAYS?_ Can your business survive an outage of unknown time? 82 | 83 | Source control doesn't replace disaster recovery. Instead, consider it a supporting tool. If I maintain a history and backup of the software over time, I can quickly redeploy it instead of waiting for the recovery process to occur. 84 | 85 | ## Recommendation for Source Control 86 | There are many options when it comes to source control. Your first decision is on your source control language (git, mercurial, tfs, svn) but I think **git** is the way to go. It works great in 99% of cases, it's open source and actively developed, and is designed for the modern way we work: disparate team members inside and out of your firewall that may have multiple dev boxes and need online/offline abilities. 87 | 88 | Next is how/where you will host your source control. Here's some options I think are best. 89 | 90 | ### GitHub 91 | 92 | [GitHub](http://github.com) is starting to become the defacto standard for all new software projects. In fact, I recommend it to all my clients. You have the option of using GitHub for free, if you don't mind all your source control being publicly available. If that's NOT an option for you (and it's okay), then you have the option to pay for "private repositories". 93 | 94 | For any repositories that you host, you're able to control who has access to it. There is no limit on the number of users you can add to a repository. 95 | 96 | Plans for individual user private repositories start as low as $7/month. For organizations with multiple users, private repository plans start as low as $25/month. 97 | 98 | ### Bitbucket 99 | 100 | [Bitbucket](https://bitbucket.org/) is another great provider of source control. They currently support unlimited private repositories for free (up to 5 users). Additional plans start as low as $10/month. 101 | 102 | ### Private On-Prem 103 | 104 | Don't want your source code to leave your private network? That's fine, git can do that too. 105 | 106 | Github has a [Enterprise install](https://enterprise.github.com) that you can run inside your network. 107 | 108 | There are open source ways to do this as well, where you have a self-hosted server that stores your code repos and maybe provides a web interface. [Digital Ocean has a good writeup](https://www.digitalocean.com/community/tutorials/how-to-set-up-a-private-git-server-on-a-vps) on this. 109 | 110 | ## Conclusions 111 | Billions of dollars is spent each year on software development and maintenance. We live in a world of bits and bytes. Changes are easy to make, but even the simplest change can be catastrophic. 112 | 113 | Source control systems have existed for over 30 years. They continue to become more sophisticated. Developers around the world trust them with their codebases because they know mistakes will happen. Make sure you're protecting your code. 114 | 115 | > Do you need assistance moving your projects forward? Let me know! Feel free to shoot me an [email](mailto:contact@consultwithgriff.com) and we can discuss options for your project. -------------------------------------------------------------------------------- /blog/Anatomy-of-an-XNA-Application.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Anatomy of an XNA Application 3 | categories: 4 | - "Development - Game Development" 5 | permalink: anatomy-of-an-xna-application 6 | updated: '2009-01-04 06:54:44' 7 | date: 2009-01-04 06:54:44 8 | --- 9 | 10 | So you have your environment set up, and you create your first XNA project.  XNA Game Studio sets up your project, and gives you a great skeleton for developing your game.  Below is the complete "Game1.cs" file you're given.  I recommend renaming this file and class to something a bit more meaningful. 11 |
using System;
 12 | using System.Collections.Generic;
 13 | using System.Linq;
 14 | using Microsoft.Xna.Framework;
 15 | using Microsoft.Xna.Framework.Audio;
 16 | using Microsoft.Xna.Framework.Content;
 17 | using Microsoft.Xna.Framework.GamerServices;
 18 | using Microsoft.Xna.Framework.Graphics;
 19 | using Microsoft.Xna.Framework.Input;
 20 | using Microsoft.Xna.Framework.Media;
 21 | using Microsoft.Xna.Framework.Net;
 22 | using Microsoft.Xna.Framework.Storage;
 23 | 
 24 | namespace LastAgent
 25 | {
 26 |     ///
 27 |     /// This is the main type for your game
 28 |     ///
 29 |     public class Game1 : Microsoft.Xna.Framework.Game
 30 |     {
 31 |         GraphicsDeviceManager graphics;
 32 |         SpriteBatch spriteBatch;
 33 | 
 34 |         public Game1()
 35 |         {
 36 |             graphics = new GraphicsDeviceManager(this);
 37 |             Content.RootDirectory = "Content";
 38 |         }
 39 | 
 40 |         ///
 41 |         /// Allows the game to perform any initialization it needs to before starting to run.
 42 |         /// This is where it can query for any required services and load any non-graphic
 43 |         /// related content.  Calling base.Initialize will enumerate through any components
 44 |         /// and initialize them as well.
 45 |         ///
 46 |         protected override void Initialize()
 47 |         {
 48 |             // TODO: Add your initialization logic here
 49 | 
 50 |             base.Initialize();
 51 |         }
 52 | 
 53 |         ///
 54 |         /// LoadContent will be called once per game and is the place to load
 55 |         /// all of your content.
 56 |         ///
 57 |         protected override void LoadContent()
 58 |         {
 59 |             // Create a new SpriteBatch, which can be used to draw textures.
 60 |             spriteBatch = new SpriteBatch(GraphicsDevice);
 61 | 
 62 |             // TODO: use this.Content to load your game content here
 63 |         }
 64 | 
 65 |         ///
 66 |         /// UnloadContent will be called once per game and is the place to unload
 67 |         /// all content.
 68 |         ///
 69 |         protected override void UnloadContent()
 70 |         {
 71 |             // TODO: Unload any non ContentManager content here
 72 |         }
 73 | 
 74 |         ///
 75 |         /// Allows the game to run logic such as updating the world,
 76 |         /// checking for collisions, gathering input, and playing audio.
 77 |         ///
 78 |         /// Provides a snapshot of timing values.
 79 |         protected override void Update(GameTime gameTime)
 80 |         {
 81 |             // Allows the game to exit
 82 |             if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
 83 |                 this.Exit();
 84 | 
 85 |             // TODO: Add your update logic here
 86 | 
 87 |             base.Update(gameTime);
 88 |         }
 89 | 
 90 |         ///
 91 |         /// This is called when the game should draw itself.
 92 |         ///
 93 |         /// Provides a snapshot of timing values.
 94 |         protected override void Draw(GameTime gameTime)
 95 |         {
 96 |             GraphicsDevice.Clear(Color.CornflowerBlue);
 97 | 
 98 |             // TODO: Add your drawing code here
 99 | 
100 |             base.Draw(gameTime);
101 |         }
102 |     }
103 | }
104 | 105 | Let's evaluate the various parts of this code. We'll ignore the using statements, and get right into the meat of the class. Below is a snippet of the code. We're given two objects, GraphicsDeviceManager and SpriteBatch. The GraphicsDeviceManager helps us determine the type of device we're going to be outputting to. This can range from various PC graphics cards to the Zune or Xbox 360. We'll use this class later to alter our output based on users environment. Next is the SpriteBatch. Think of this as a List<> of images you want to draw to the screen. This will be covered a little bit later in the Draw() method. 106 | 107 | Next is the game class constructor, which sets up the GraphicsDeviceManager and sets our Content pipeline. The content pipeline is a post all in itself, so don't worry too much about it now. The Initialize() method provides you a place to do anything you need to do before the game runs. I'm at a loss for a good example of what you would put here, but if I ever think of one, I'll be sure to let you know. 108 | 109 |
110 | GraphicsDeviceManager graphics;
111 |         SpriteBatch spriteBatch;
112 | 
113 |         public Game1()
114 |         {
115 |             graphics = new GraphicsDeviceManager(this);
116 |             Content.RootDirectory = "Content";
117 |         }
118 | 
119 |         ///
120 |         /// Allows the game to perform any initialization it needs to before starting to run.
121 |         /// This is where it can query for any required services and load any non-graphic
122 |         /// related content.  Calling base.Initialize will enumerate through any components
123 |         /// and initialize them as well.
124 |         ///
125 |         protected override void Initialize()
126 |         {
127 |             // TODO: Add your initialization logic here
128 | 
129 |             base.Initialize();
130 |         }
131 | 
132 | 133 | Next are our Load and Unload content methods. The purpose of these methods are to load all the content you need to start the game. The comment says "load all your content", but realistically you don't want to do that. For demos, this is ok. For commercial games, you want to load as little as possible to get the user going and load as necessary. That's what loading screens are for! 134 | 135 |
136 |         ///
137 |         /// LoadContent will be called once per game and is the place to load
138 |         /// all of your content.
139 |         ///
140 |         protected override void LoadContent()
141 |         {
142 |             // Create a new SpriteBatch, which can be used to draw textures.
143 |             spriteBatch = new SpriteBatch(GraphicsDevice);
144 | 
145 |             // TODO: use this.Content to load your game content here
146 |         }
147 | 
148 |         ///
149 |         /// UnloadContent will be called once per game and is the place to unload
150 |         /// all content.
151 |         ///
152 |         protected override void UnloadContent()
153 |         {
154 |             // TODO: Unload any non ContentManager content here
155 |         }
156 | 
157 | 158 | The last two methods are the meat of your XNA application. The Update() method is provided to you as a way to update the state of your game. As the comment says, you use this method to update your world, check for collisions, gather input, play audio, etc. By default, you're given code that will detect a button press from an Xbox 360 controller. Keep in mind when designing your games if you are going to accept input from just a 360 controller, keyboard, mouse, or all of the above. 159 | 160 | Finally, there is the Draw method, and this is where all your content makes it onto the screen. The first line clears the screen. This is a very necessary step. Failing to clear the screen would lead to some wacky results. Think of the screen as a canvas. You can't simply redraw on top of what you've already drawn. Calling the clear method results in a new canvas. This screen is where our friend SpriteBatch will come in handy. 161 | 162 |
163 |         ///
164 |         /// Allows the game to run logic such as updating the world,
165 |         /// checking for collisions, gathering input, and playing audio.
166 |         ///
167 |         /// Provides a snapshot of timing values.
168 |         protected override void Update(GameTime gameTime)
169 |         {
170 |             // Allows the game to exit
171 |             if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
172 |                 this.Exit();
173 | 
174 |             // TODO: Add your update logic here
175 | 
176 |             base.Update(gameTime);
177 |         }
178 | 
179 |         ///
180 |         /// This is called when the game should draw itself.
181 |         ///
182 |         /// Provides a snapshot of timing values.
183 |         protected override void Draw(GameTime gameTime)
184 |         {
185 |             GraphicsDevice.Clear(Color.CornflowerBlue);
186 | 
187 |             // TODO: Add your drawing code here
188 | 
189 |             base.Draw(gameTime);
190 |         }
191 | 
192 | 193 | And that's about it! Press Ctrl-F5 to build and run your first XNA application. You should be greeted with a pretty, Cornflower Blue screen. What you're not seeing is your Update and Draw methods being called continuously. 194 | 195 | What's next for our little application? For starters, we need to get some stuff on the screen. For my game, I'm going to be using a tile based game, so my next entry will revolve around loading tile sets and drawing them to the screen. 196 | 197 | Happy developing! -------------------------------------------------------------------------------- /blog/Non-Tech-Factors-to-Consider-When-Choosing-Your-Tech-Stack.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Non-Tech Factors to Consider When Choosing Your Tech Stack 3 | categories: 4 | - Deep Thoughts 5 | permalink: non-tech-factors-to-consider-when-choosing-your-tech-stack 6 | date: 2016-05-10 21:33:01 7 | --- 8 | 9 | Greenfield projects are typically a great deal of fun. It is something new and exciting! No legacy code that will bog down or needlessly frustrate the team. *We will finally get to do things the RIGHT way this time.* 10 | 11 | There is a flip side to this excitement, however. The fun and flexibility of a new Greenfield project also comes with the unparalleled responsibility of making hard, up front, technical decisions. 12 | 13 | Ask any developer who has worked on a long-term project and they will tell you that there are some things you cannot simply change halfway through the development of a project. At least not without hundreds of man-hours of effort to remedy. Should we use an ORM or write ADO.NET by hand? ASP.NET Core 1.0 or go with tried-and-true ASP.NET 4.6. MVC or 14 | WebForms? The hard technical decisions you make at the beginning of the project can echo for years! 15 | 16 | >For some guidance on how to select your ASP.NET tech stack, watch this 17 | on-demand webinar on [*Choosing the Right Tech Stack*](http://www.telerik.com/campaigns/devcraft/choosing-the-right-tech-stack?utm_medium=external&utm_source=kgriffin&utm_campaign=dt-devcraft-apr16-webinar&utm_content=article) - (sponsored). 18 | 19 | Because it is so challenging, many developers will concentrate on the technical aspects of selecting a stack while completely ignoring the developers themselves. If you are the technical director of a project, you cannot proclaim “this is the stack we will use” without a firm understanding of how that will be accepted by the team or even simply the knowledge of what the needs of the project will be. 20 | 21 | ##Being on the Cutting Edge 22 | There is a poem by Robert Frost that every high school kid in the US had to memorize. Two roads diverged in a yellow wood, and sorry I could not travel both.* Your tech stack is the same. There are two paths: one that is well worn and one that is thick with undergrowth. 23 | 24 | Which one do you select? 25 | 26 | First, we can examine the well-worn path. ASP.NET WebForms has been around for over fifteen years. There are a million different blog posts on various aspects of WebForms. As it has matured over the years, most of the documentation has stayed relevant. Try Googling for “(something) webforms” and you will be rewarded with thousands of results. All of which are probably still good to examine and use! 27 | 28 | ASP.NET MVC 5 is an in-between of tried and true and cutting edge. With the onset of ASP.NET Core 1.0, using MVC 5 on ASP.NET 4.6 is a bit like buying a car one model year older when the new ones are shipping next week. However, as with cars, the documentation and trailblazing has already happened. You benefit from all the hard work of previous 29 | early-adopters. 30 | 31 | ASP.NET Core 1.0 is the overgrown road. If you were to glance down it, you would see developers who have tripped and fallen. Some might be stuck in holes. The end of the road is a mystery because it isn’t visible from where you are. Ask yourself, "How adventurous do I feel?” 32 | 33 | Projects with strict budgets and deadlines would not be appropriate for cutting edge. That conversation doesn’t go well. 34 | 35 | >“Are we all set with the launch next week?” 36 | > 37 | >“No. Turns out ASP.NET Core doesn’t support SmtpClient yet so we have to push a few weeks.” 38 | 39 | On a personal note, I like to stay on in the middle leaning towards cutting edge. My job dictates that I solve business problems and doesn’t require a specific tech stack. For a current client project, I’m adventuring into ASP.NET Core and I’m hitting far more roadblocks than what I was expecting. 40 | 41 | Trailblazers need to be aware and take their time. Through their efforts, the path will be clearer for other developers who follow. 42 | 43 | ## Developer Ability to Learn Quickly 44 | 45 | When I used to hire developers, our metrics did not put too much concern about what a person knew but how quickly he or she could learn it. 46 | 47 | When choosing a stack, it is important to gauge the team responsible for implementing the stack. A developer fixated with developing for WebForms might have a difficult time moving to the more complex patterns exposed by ASP.NET MVC or WebAPI. 48 | 49 | A colleague of mine has told a story about one of his old bosses who had a deprecated background in software development. In the story, the boss had been spending months trying to learn how C\# worked and he was attempting to cobble together a WinForms application based off knowledge he copied from books and online tutorials. One day, the boss called my colleague into his office and asked him to explain what a class was. 50 | 51 | Our goal isn’t to alienate developers. Everyone learns in different manners and at different rates. When selecting a tech stack, we need to remain conscious of who will be implementing the solutions and if they mentally can handle the pressure of being towards the cutting edge. 52 | 53 | What’s better? A complete solution in an older technology or an incomplete solution that is on the cutting edge. 54 | 55 | ## What does the project need? 56 | 57 | All projects are unique snowflakes. Client needs will vary from “I just need something better than this Excel spreadsheet” to “I want something like Facebook”. 58 | 59 | Simple “forms over data” applications do not need to be single page applications built with Angular 2 or React. A complex solution that would take a small team of developers to implement over a couple weeks can easily be accomplished by one developer within a couple hours with WebForms. 60 | 61 | Large monolithic web applications have a different set of needs. You are expecting these projects to launch with minimum features, but eventually will balloon in size and complexity. The time invested in more cutting edge approaches will pay dividends in the future. 62 | 63 | Your goal as a decision maker is to weigh the needs of the project with the tools available – and even in some cases, looking at the tools on the horizon. If your project is simply forms over data, maybe stick with something simple like ASP.NET WebForms. If you foresee the project growing in complexity over time, maybe start with an ASP.NET MVC and WebAPI stack that could later integrate front-end frameworks like Angular or React. 64 | 65 | ## Team Size and Scalability 66 | 67 | Another important factor to think about in your quest for the perfect tech stack is the size of the team that will construct the project. 68 | 69 | I have had the pleasure of working in both small, one to two person teams and additionally been part of larger teams that have spanned multiple people around the world. 70 | 71 | As the CTO for a startup, our team brushed up against the most bleeding edge technology we could get our hands on. During the course of a day, we would deploy a dozen times to production. There was a mutual agreement and respect for the project, and our team cohesion allowed flexibility to make fast, uncalculated decisions on tools, libraries, or 72 | frameworks. If the tool didn’t work, no big deal – toss it out and try another. 73 | 74 | If I were to travel the startup road again, I would guide my team toward adopting ASP.NET Core. Even in its infancy, there is potential for this platform to allow us more agility than previous versions of ASP.NET. 75 | 76 | The first major development team I worked with out of college was for a large security company developing components for anti-virus software. This team moved at a much slower pace. Our requirements called for a deployment every quarter, and our software was supported across a dozen operating systems. Changes in the tools and frameworks we used impacted dozens of developers across the world. 77 | 78 | If change was enacted, our teams needed to also prepare for the blowback. What happens when you have not considered every angle? What is plan B if you hit a roadblock? Who makes the decision of how to navigate roadblocks? 79 | 80 | Please don’t misunderstand; there are large teams that are perfectly capable of quick deployments and rapidly changing direction when the project calls for it. My argument is that the majority of larger teams I’ve been with absolutely cannot work in this capacity. If you have a 30-person team, and you tell them to use ASP.NET Core 1.0, which is the 81 | bleeding edge of what ASP.NET developers can use, then you need to expect them to adjust for API-breaking changes every couple weeks. It is rare to find a large team able to do that without going insane or ultimately pushing back the schedule. 82 | 83 | ## Conclusions 84 | 85 | 86 | Sometimes we wish decisions could simply be a matter of bits and bytes, but there are many human factors that need to be taken into account. 87 | 88 | The best advice that can be given is to discuss the pros and cons of every choice available within your teams. If teams are completely involved in the process of making technical decisions, the product outcome will be better because of it. 89 | 90 | > What tools are available in the ASP.NET stack then? Jeremy Likness has an [excellent 91 | article](http://developer.telerik.com/featured/how-to-web-asp-net/?utm_medium=external&utm_source=kgriffin&utm_campaign=dt-devcraft-apr16-webinar&utm_content=article) on the current state of ASP.NET development tools. Use the tools discussed in Jeremy’s article to start a dialog with your team. (sponsored) 92 | 93 | A great team, when given flexibility, will always produce a solid product. -------------------------------------------------------------------------------- /blog/Review-Everleap.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Review: Everleap' 3 | categories: 4 | - Reviews 5 | permalink: everleap 6 | date: 2014-10-20 17:43:01 7 | --- 8 | 9 | *For this review, I am being provided a free account at Everleap for hosting my user group, the Hampton Roads .NET Users Group. If you are interested in a place to host your own group’s site, please talk to the folks at Everleap!* 10 | 11 | *This review is also cross-posted at http://www.codeproject.com/Articles/827619/Review-Everleap* 12 | 13 | *Interested in trying Everleap out for yourself? Head [here](http://www.everleap.com/a/kevgriffin).* 14 | 15 | Something I haven't had to do in a while is shop around for a hosting provider. To be perfectly honest, since Windows Azure starting offering Websites, there has been little need for me to look elsewhere. With our user group, it has been a hassle to host the site with my personal Azure account. It was natural for us to start looking at alternatives that didn’t tie the group site to me. 16 | 17 | ## What is Everleap? ## 18 | Everleap is a hosting service by the good folks who brought us DiscountASP.NET. It is promoted as a reliable, scalable, and affordable hosting platform built on top of the Windows Azure Pack. 19 | 20 | The Windows Azure Pack is a framework that allows hosting providers to leverage the same technology behind the Windows Azure platform. 21 | 22 | With traditional hosting, you are normally locked into a plan with limited resources. If you were to use more than the resources you were provided, either your site would be taken offline or you would be charged for the overages. 23 | 24 | Cloud services revolutionized the industry by giving us the opportunity to deploy applications once and scale the resources depending on our use cases. If you need more resources, scale up. If you need fewer resources, scale down. Pay for what you use! 25 | 26 | Everleap offers all of the above, but at a low, fixed monthly rate. Need extra resources? Everleap offers the "power pack" which gives you a bump in resources without breaking the bank. 27 | 28 | ## Setting up an account ## 29 | Sign up is painless. Give your name, email, and credit card information and select the type of plan you want to sign up for. 30 | 31 | For my review, I was provided with a complementary license for Everleap’s “Cloud Websites” offering. This option provides me with one website, scalable across 2 servers. There is also an option for “Mulit-Domain Cloud” which gives you the ability to manage up to five websites across two servers. Resources and bandwidth limitations still apply for both, but the limits are not unreasonable. 32 | 33 | One of my largest gripes is that Everleap doesn't let you choose a login name for yourself. After you sign up and confirm all your information, you're left with just a login prompt. 34 | 35 | To get a username, you are supposed to check your email where you realize you have been assigned a random username. I’ve been told by Everleap associates that this is on the product backlog to correct. 36 | 37 | ![Everleap Welcome Email](https://griffcdn.blob.core.windows.net/kevgriffinpublic/everleap-1.png) 38 | 39 | ## Exploring the Control Panel ## 40 | 41 | A great way to describe the control panel for Everleap is "clean". 42 | 43 | ![Hosting Overview](https://griffcdn.blob.core.windows.net/kevgriffinpublic/everleap-2.png) 44 | 45 | ![Cloud Website Overview](https://griffcdn.blob.core.windows.net/kevgriffinpublic/everleap-3.png) 46 | 47 | Everleap does a great job of giving you "at a glance" information about your sites. How much hard drive space is it taking up? How much bandwidth have you used this month? 48 | 49 | ![Site tools](https://griffcdn.blob.core.windows.net/kevgriffinpublic/everleap-4.png) 50 | 51 | Do you need to take the site down or want to recycle the process? Easy use buttons are on the right of the screen, ready to serve you. 52 | Over in site settings, I had a bit of a weird déjà vu feeling. Going through each section, the settings available to me were identical to those your get in Windows Azure. This is great though! It is a huge benefit of Everleap being built on top of the Azure Pack. 53 | 54 | ![General settings](https://griffcdn.blob.core.windows.net/kevgriffinpublic/everleap-5.png) 55 | 56 | The settings also give away a couple hints about the type of applications we can deploy to Everleap. On one screen, there is an option for PHP and for Classic ASP. You are not tied to just building ASP.NET applications. 57 | 58 | Most exciting for me is the App Settings screen where one of the options is WEBSITE\_NODE\_DEFAULT_VERSION. A quick double check of https://www.everleap.com/cloud-hosting/web-sites/overview/ shows that node.js is supported and encouraged! 59 | 60 | ## Deploying an Application ## 61 | Everleap provides three ways to deploy your application. 62 | 63 | ● FTP 64 | ● Web Deploy 65 | ● Git 66 | 67 | For FTP and WebDeploy, Everleap provides you with a publish profile to use within Visual Studio. Simply click "Download" next to either option, and save the file somewhere safe. 68 | 69 | ![FTP and Web Deploy](https://griffcdn.blob.core.windows.net/kevgriffinpublic/everleap-6.png) 70 | 71 | Setting up web deploy in Visual Studio is painless. Right click on your web project, and select Publish. 72 | 73 | ![Publish options are in Visual Studio](https://griffcdn.blob.core.windows.net/kevgriffinpublic/everleap-7.png) 74 | 75 | ![The Publish Web Dialog will import settings from Everleap](https://griffcdn.blob.core.windows.net/kevgriffinpublic/everleap-8.png) 76 | 77 | If you've never published this project before, you will want to "Import" a publish profile. Select the publish profile you downloaded earlier, and Visual Studio will pre-fill all the options with settings from Everleap. 78 | 79 | Press "Publish" and Visual Studio will connect to Everleap, upload all your files, and perform any additional configuration needed (such as setting database strings, etc). 80 | 81 | ## Scaling ## 82 | Depending on the popularity of your application, you might have the need to scale. With traditional hosting platforms, this is where you can hit a wall. With Everleap, scaling is as easy as saying you need "2" cloud servers instead of "1". 83 | 84 | ![One server, or two](https://griffcdn.blob.core.windows.net/kevgriffinpublic/everleap-9.png) 85 | 86 | This change doesn’t happen instantly, and Everleap does not communicate the progress between moving from 1 to 2 servers. When I started performance testing, I had to wait about 5 minutes after pressing “Update” until the second server was allocated for me. 87 | Everleap associates made me aware of a backlog issue to implement a system-wide notification system, which would easily correct the issue I had above. 88 | 89 | ## Performance ## 90 | When testing a hosting solution, I like to see how it performs under stress. To test Everleap, I created two different tests. These tests are not meant to be exhaustive. My goal is to see how Everleap handles a decent amount of load over time. The site deployed for this test is the sample ASP.NET application Visual Studio generates. 91 | 92 | ### Test 1: 0 to 1000 clients over 1 minute ### 93 | 94 | This is a test I like to run in order to see how well my site will perform as more and more people start connecting to it. 95 | 96 | ![Load of 1000 clients over 1 minute](https://griffcdn.blob.core.windows.net/kevgriffinpublic/everleap-10.png) 97 | 98 | This test did very well. The spike in response time at the beginning of the test is due to ASP.NET warm up, but afterwards the response time does a good job of saying underneath 250ms. Our average for this test was 134ms, is nothing to scoff at. The server was performing as expected! 99 | 100 | ### Test 2: 5000 clients per second over 1 minute ### 101 | 102 | ![One server, 5000 connections per second over one minute](https://griffcdn.blob.core.windows.net/kevgriffinpublic/everleap-11.png) 103 | 104 | This test sent a constant load of 5,000 client connections to the server over a 1 minute period. Imagine your website being posted on Reddit, Slashdot, or Good Morning America. The demand for your page would be immediate over a short period of time. In fact, when I discuss performance with clients, this is a use case we always imagine. You never want your site to error when it is hitting critical mass. 105 | 106 | The average response time hovered around 133ms, which is really good! 107 | 108 | There were 280k successful requests made, and 19k errors (500 status). The error rate of 6.4% should be concerning, but not unwarranted. We are throwing a lot of traffic at one server, and there is only so much traffic a server can take. 109 | 110 | The second part of the test was to scale the environment to 2 servers. 111 | 112 | ![Two server, 5000 connections per second over one minute](https://griffcdn.blob.core.windows.net/kevgriffinpublic/everleap-12.png) 113 | 114 | The response time went from 133ms average to 73ms average and we eliminated all of the errors we were receiving before. Everleap did a great job dealing with the traffic. 115 | 116 | ## Conclusions ## 117 | 118 | Everleap did a great job of giving me what I want from a hosting provider. 119 | 120 | ● Quick, easy registration 121 | ● Multiple, dependable methods of deployment 122 | ● Configuration options 123 | ● Scalable 124 | ● Performant 125 | 126 | During the process of evaluating Everleap, I had coffee with a friend of mine who is a fellow consultant. We discussed the differences between traditional hosting, cloud providers, and then Everleap. 127 | 128 | Everleap popped out as an excellent alternative for him over Windows Azure, since his clients react better to fixed pricing than having to deal with usage scenarios. 129 | 130 | If you're looking for the power and flexibility of Windows Azure and you need the pocket friendliness of a monthly fixed price, then you shouldn't look any farther than Everleap. 131 | 132 | You can visit their site to find out more about the [Everleap](http://www.everleap.com/a/kevgriffin) Cloud. 133 | -------------------------------------------------------------------------------- /blog/Shedquarters.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Shedquarters 3 | date: 2017-05-26 12:57:44 4 | categories: 5 | - Business 6 | permalink: shedquarters 7 | --- 8 | 9 | ## May 25th, 2017 10 | Since 2009, I have worked out of my home office, the FROG (finished room over garage). Since then, life has changed a bit. I have three awesome little boys who are growing up to be school age, and my wife and I need a part of the house dedicated to homeschooling. 11 | 12 | The FROG is the obvious location. When you have three kids, room to spare is a luxuary not often found. 13 | 14 | But in order to use the FROG for homeschooling, I need to vacate. I could've rented office space for $750-$1500 per month. But have you ever tried to RENT a single or double office? They're **really** hard to find at reasonable rates. 15 | 16 | And I like working at home. Adding a commute back into day to day would really put a bummer on my personal and business life. There needed to be a better alternative. 17 | 18 | Today, I bought my **Shedquarters**. 19 | 20 | >Note: These are the model I bought, but mine is more customized. 21 | > 22 | >![](https://griffcdn.blob.core.windows.net/kevgriffinpublic/shedquarters/model_1.jpg) 23 | >![](https://griffcdn.blob.core.windows.net/kevgriffinpublic/shedquarters/model_2.jpg) 24 | 25 | The pictures above show the "base" model of the building I'm buying. My shed will have a real door on the right hand corner, and windows going all the way around. 26 | 27 | And the entire thing will be unfinished. Part of my fun is insulating, drywalling, and running power/internet out to the building. 28 | 29 | This post will be a story of the work I do on my Shedquarters, and also an overview of the costs associated with owning it. 30 | 31 | ## June 17th, 2017 - Area Prep 32 | Here is a *before* picture of where there Shedquarters is going to live. 33 | 34 | ![](https://griffcdn.blob.core.windows.net/kevgriffinpublic/shedquarters/ShedPlotBefore.jpg) 35 | 36 | Normally with these types of sheds, they can just be dropped on the ground or put up on blocks. That's not a *bad* way to secure the shed, however, this area is prone to holding water when it rains. Several *epic* rainstorms recently have caused me to reevaluate the foundation for my Shedquarters. 37 | 38 | Ideally, I would have just poured a concrete slab. It's most likely to last the longest. The *best* estimate I got was $1,900 and I'd have to wait 2-3 weeks before the work could be done. 39 | 40 | I'm not opposed to a bit of hard work, so I went for a compromise of pouring concrete piers. Think "fence posts" but without the fence. 41 | 42 | Since these sheds are turnkey, I already knew where the piers should go. 43 | 44 | ![](https://griffcdn.blob.core.windows.net/kevgriffinpublic/shedquarters/ShedPlotMarkedOut.jpg) 45 | 46 | Each "line" is ~64 inches from the other lines and have 5 crosses in them. A total of 15 piers. 47 | 48 | Each "pier" will be 30 inches deep and 8 inches wide. The exposed part of the pier will be 12 inches wide. This should give me PLENTY of margin for measurement errors. 49 | 50 | ## June 23th, 2017 - PERMITS 51 | I decided to get a permit. Technically, it's required by the city even if the structure is non-permanent. But this will add to the resale value of my home, and I need to add it to my homeowners insurance. It's important that I make sure all the details are in place. 52 | 53 | There are three conditions I have to meet: 54 | 55 | 1. Provide architectural drawings of the building 56 | 2. Anchor the building to the ground 57 | 3. Building has to have a flood vent 58 | 59 | Since my area is in a flood zone, it is possible (unprobable) that we could get SO MUCH RAIN that the shed floats away. My shed requires 6 anchors total, one in each corner and two in the middle. 60 | 61 | Getting the drawings was fairly easy! I just asked. Since the company I'm using does this so often, the manager had them ready to go. 62 | 63 | ## June 24th, 2017 - HARD WORK 64 | Digging holes is hard work. I threw money at the problem and rented a towable auger for a day. 65 | 66 | ![](https://griffcdn.blob.core.windows.net/kevgriffinpublic/shedquarters/TowableAuger.jpg) 67 | 68 | With the help of my dad and brother-in-law, we dug out 15 holes - each about 30 inches deep. As I said above, the area is prone to holding water, so the holes filled up pretty quickly! This process took about 30 minutes total. Much easier than digging out holes by hand. 69 | 70 | ![](https://griffcdn.blob.core.windows.net/kevgriffinpublic/shedquarters/DiggingHoles.jpg) 71 | 72 | Once all the holes were dug, I cut concrete forms and leveled them all with the highest point in the area. Then I dumped a bag or two of concrete into the holes. Because of the amount of water in the holes, we didn't mix the concrete first. If you dump the bag, it can be mixed *in* the hole - saving a ton of time and effort. 73 | 74 | Along with concrete, I added 3 pieces of rebar to secure the bottom part of the pier to the footing itself. 75 | 76 | These had to sit overnight. 77 | 78 | ![](https://griffcdn.blob.core.windows.net/kevgriffinpublic/shedquarters/AllHolesDug.jpg) 79 | 80 | ## June 25, 2017 - Pouring Footings 81 | After giving the base of the footings a day to dry, we poured the footings. The concrete for these had to be mixed by hand 82 | 83 | ![](https://griffcdn.blob.core.windows.net/kevgriffinpublic/shedquarters/PouredAndReady.jpg) 84 | 85 | Next is the FUN part! The shed delivery! 86 | 87 | ## July 10th, 2017 - Shed Delivery! 88 | FINALLY! The Shedquarters came today! After all the prep to ensure that we would have a stable foundation to put the shed on, this was the moment of truth. 89 | 90 | The shed showed up on my driveway! 91 | 92 | ![](https://griffcdn.blob.core.windows.net/kevgriffinpublic/shedquarters/ShedDelivery.jpg) 93 | 94 | The entire process took about 20 minutes. There was a team of 3 guys, and they backed the shed into my backyard and dropped it on the footings I had poured. And guess what, the footings were near perfect! 95 | 96 | Here's a video of the dropping process: 97 | 98 | 99 | 100 | ## August 27th - Progress on the interior 101 | I had several weeks in August that I wasn't able to work on the shed, but progress has been coming along smoothly. 102 | 103 | There are three major things that got done in the Shedquarters. 104 | 105 | First, we ran electrical wiring throughout the entire building. Because outlets are prime real estate, I opted to have as many as I could. 106 | 107 | Soon, my electrician is going to run a 100 amp subfeed from my house out to the shed. This subfeed will run two circuits for outlets, circuits for my AC and heating unit, and circuits for exterior lighting and outlets. 108 | 109 | To test the electrical outlets, we wired up up a heavy duty extension cord to "plug" the shed into my house. Works great until you blow a breaker once or twice. At least it's temporary. 110 | 111 | We also had to install 2x4 beams across the roof to hang drywall from. Here is a picture of the completed work: 112 | 113 | ![](https://griffcdn.blob.core.windows.net/kevgriffinpublic/shedquarters/ShedFloorBeams.jpg) 114 | 115 | Once the beams were in, we could hang the recessed LED lights I bought. I'll have 8, in total, plus a ceiling fan in the middle of the room. These LEDs throw a ton of light, and do a great job of filtering it across everywhere. 116 | 117 | ![](https://griffcdn.blob.core.windows.net/kevgriffinpublic/shedquarters/ShedLighting.jpg) 118 | 119 | Next step - ETHERNET and real power. 120 | 121 | 122 | # FAQ 123 | 124 | ## Did you a permit? 125 | 126 | According to the city, I did need a permit. The entire process was painless. I told the building permits people at city hall what I was doing, and they directed me exactly where I needed to go. A couple bucks later - I'm done. After the shed was installed, I had to anchor it and call the city back out to do the final inspection. That process was all online, and literally took 5 minutes when the guy got here. Most of that was chatting about how awesome my Shedquarters is going to be. 127 | 128 | ## Do you have an HOA (Homeowners Association)? 129 | 130 | HECK NO! I won't go into the pros and cons of a HOA - but I prefer not having to ask permission for what I want to do on my property. 131 | 132 | 133 | What are you questions? Ask in the comments or on [Twitter](https://twitter.com/1kevgriff) 134 | 135 | # Costs 136 | How much does it cost to build out a Shedquarters? I'm trying to include Virginia Sales Tax as well (6.00%). 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 |
ItemCost
Shed$5,796.08
Building Permit (City of Chesapeake)$91.74
Towable Auger Rental$127.01
5 - Bags of Gravel$20.35
45 - 2Ft Rebar$88.25
4 - 48" Concrete Form Tubes$67.71
39 - Bags of Concrete (60lbs)$176.60
Electrical Boxes (Home Depot)$7.45
Electrical Boxes (Lowes)$4.29
Anchors (city requirement)$44.27
8 - LED Recessed Bulbs$76.28
8 - Recessed Light Housings$60.89
2 - LED Light Switches$48.70
2x4 (Variety of Lengths)$110.45
Misc Costs$61.56
Total$6,781.63
-------------------------------------------------------------------------------- /blog/Paying-Attention.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Paying Attention 3 | permalink: paying-attention 4 | date: 2015-07-23 06:43:54 5 | categories: 6 | - Deep Thoughts 7 | --- 8 | 9 | Last week I did a training gig for a great group of folks out on the west coast. I worked from the comfort of my home office, and presented all the material remotely. 10 | 11 | The spec for training was pretty straightforward: start at 9am and end at 5pm for three days. The timezone was for Pacific Time, since the majority of the group resided in that timezone. 12 | 13 | This week, I did a training for the same company but with a different group of people. Monday morning I woke up bright and early to an email wondering why I was a no-show to the training. Of course, I was barely out of bed and hadn't had my coffee yet. I'm an east coaster, so 9am Pacific Time would've been noon local time. Training didn't start for a few hours. 14 | 15 | I quickly reviewed my spec, and I saw it plain as day: 9am to 5pm. What was I missing? 16 | 17 | Central European Time. Or better known as 3am to east coasters. YIKES! I was a no show. 18 | 19 | The moral of the story is that we need to start paying better attention. Too often do we get lost in the small details or we simply assume too much. For me, I assumed since the first training was Pacific Time Zone that the second one was Pacific Time Zone as well. Heck, I even checked the spec! But I only checked the times, and completely overlooked the different timezone. A 9 hour mistake. 20 | 21 | Luckily for me, the client was understanding and we pushed the training another day. 22 | 23 | Have you ever had a moment where your assumptions got the best of you? Minute details completely escaped you even though you were staring right at them? I'd love to hear about it! Leave me a comment and let us share the pain together. 24 | 25 | 323 |
324 | 325 | 326 | 327 | 328 | 329 | 330 |
331 |
332 |
333 |
334 |
335 |

336 | I really hope you enjoyed this post, and I especially hope you learned something new today because of it. 337 |

338 |

339 | If you don't mind, I would love to send you more great knowledge packed emails (promise no more than 1 per week!). 340 |

341 |

342 | 343 | Sign up below! 344 | 345 |

346 |
347 |
348 |
349 |
350 |
351 |
352 | Full Name 353 |
354 |
355 | 356 |
357 |
358 |
359 |
360 |
361 |
362 | Email * 363 |
364 |
365 | 366 |
367 |
368 |
369 |
370 |
371 |
372 | 373 |
374 |
375 |
376 |
377 |
378 |
379 | email marketing 380 | by activecampaign 381 |
382 |
383 |
384 |
385 | -------------------------------------------------------------------------------- /blog/Books-I-Read-in-2016.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Books I Read in 2016 3 | categories: 4 | - Reflection 5 | permalink: books-i-read-in-2016 6 | date: 2016-12-30 08:01:38 7 | --- 8 | 9 | Reading is amazingly important. A long time ago I read a book that discussed traits of successful people, and the number one similarity I saw was that successful people tend to read A LOT. Since 2016 is wrapping up, I took a couple minutes to look through the list of books I was able to get through. 10 | 11 | My list distinctly separates fiction from non-fiction. I *love* reading good fiction, and it's just as important for stories and fantasy to be a part of your reading schedule as it is to read non-fiction. Escape a little! 12 | 13 | I'm going to list the books in no particular order! I won't give much commentary, because I'd love to hear your thoughts in the comments. By the way, there are affiliate links to Amazon. If you use my link to pick up the book, I'd greatly appreciate it! 14 | 15 | ## Non-Fiction 16 | 17 | [You're Never Weird on the Internet](http://amzn.to/2iM7eVY) by Felicia Day 18 | 19 | I picked this book up on a whim. I've been a big fan of Felicia Day since the early episodes of The Guild. If you're enjoyed any of her work, this book is a quick read and a glimpse into her mind and background. 20 | 21 | * * * 22 | 23 | 24 | [MONEY Master The Game: 7 Simple Steps to Financial Freedom](http://amzn.to/2iLWcjI) by Tony Robbins 25 | 26 | I think a lot about personal finance, and how to prepare myself and my family for the future. I wouldn't necessarily recommend this book to someone with no basic understand of personal finance. It goes DEEP quickly, and I'm anticipating multiple reads to get the full value out of it. 27 | 28 | * * * 29 | 30 | 31 | [How to Win Friends and Influence People](http://amzn.to/2hzRDLD) by Dale Carnegie 32 | 33 | My first time reading this book. Not my last. If you deal with people at all, it is a must read. 34 | 35 | * * * 36 | 37 | 38 | [The Big Fat Surprise](http://amzn.to/2hzXFfa) by Nina Teicholz 39 | 40 | I've tackled weight problems for most of my life. The best success I've ever had has been on the ketogentic diet. Traditional philosophy failed me. Come to find out, traditional thinking on diets is completely wrong, and possibly killing people. This book provides a ton of research and science into why we've been lied to regarding nutrition. 41 | 42 | As a side note, I've done a bit of research outside of this book and I tend to agree with most of what it says. Everyone is different, so do your own research and form your own opinions. 43 | 44 | ---- 45 | 46 | 47 | [How to Fail at Almost Everything and Still Win Big](http://amzn.to/2iNicim) by Scott Adams 48 | 49 | Also picked up on a whim. If you feel like you're failing or not progressing fast enough, give this book a read. Scott Adams is the guy who write Dilbert. That wasn't an overnight success. There were dozens of failed experiments before Dilbert, all providing Scott Adams with new knowledge and skills. And it's funny! Well worth your time. 50 | 51 | * * * 52 | 53 | 54 | [The 4-Hour Body](http://amzn.to/2iMEuN6) by Tim Ferris 55 | 56 | I like how Tim Ferris forms opinions by experimenting on himself, and usually in the presence of an expert. Take a lot of his advice with a grain of salt. Do your own research. SHORT read. The Audible version of this book is 4-5 hours long. 57 | 58 | * * * 59 | 60 | 61 | [Never Split the Difference](http://amzn.to/2hCtDJw) by Chris Voss 62 | 63 | My favorite book of the year. Chris Voss is an ex-FBI negotiator. He goes into details about how you can use the tactics of the FBI for negotiating can benefit you in business and in life. Must read! 64 | 65 | ##Fiction 66 | 67 | 68 | [Ready Player One](http://amzn.to/2hAc9eX) by Ernest Cline 69 | 70 | A very enjoyable book to read! Especially as VR is becoming more of a "thing", you can see the horizon of this futuristic book coming forth. 71 | 72 | * * * 73 | 74 | 75 | [Redshirts](http://amzn.to/2hA3SYz) by John Scalzi 76 | 77 | Imagine Star Trek, and the "redshirts" figure out they always die on away missions. Take that idea and RUNNNNNN with it. 78 | 79 | * * * 80 | 81 | 82 | [Order to Kill](http://amzn.to/2iMLoC4) by Vince Flynn and Kyle Mills 83 | 84 | I'm a huge fan of spy, counter-intelligence type of books. The Mitch Rapp character is one of my favorites. Sadly, the author Vince Flynn passed away a couple years ago. However, the character lives on through a new author! 85 | 86 | * * * 87 | 88 | 89 | [Running Blind](http://amzn.to/2ifAjMC) by Lee Child 90 | 91 | Jack Reacher books scratch the same itch as Mitch Rapp does. If you've seen the movie, the book series is 1000x better! While this isn't the best book in the series, it was still good on it's own. 92 | 93 | ## What are your favorite reads? 94 | You've seen the books I read and enjoyed! What have you read this year? I love recommendations! --------------------------------------------------------------------------------