Thursday, January 17, 2019

Things I've Been Learning Lately in Software Dev (mostly C# .net core)

.Net Core 2.0, to include an HTML fragment into a .cshtml page:

    @await Html.PartialAsync("~/Views/Shared/_Address.cshtml")

To prepare for Dependency Injection in .Net Core 2.0

public void ConfigureServices(IServiceCollection services)
 {
     services.AddSingleton(provider => Configuration);
     services.AddTransient<IUserRepository, UserRepository>();
     services.AddSingleton<IMailer, SmtpMailer>();
 }

Create simple Moq object in C#

var imailerMoq = new Mock();
imailerMoq.Setup(x => x.SendEmail(It.IsAny(), It.IsAny())).Returns(true);

How to return async task for a unit test

public async Task GetAwesomeString() {
   return await Task.FromResult("I'm the awesome returned text");
}

sudo -s //makes the entire session root

In C# you cannot downcast an object, only cast an object upwards:

wrong    Sheep sheep = (sheep)mammal;
right  Mammal mammal = (Mammal)sheep;

C# -- to get prettyprint of json object with indentation:

var json = JsonConvert.SerializeObject(myObject, Formatting.Indented);

C# to get a key from a value:

Dictionary dictionary = GetMyDictionary();
var name = dictionary.FirstOrDefault(x => x.Value == id).Key;

To change the prompt in linux:

echo "PS1='\w\$ '" >> ~/.bash_profile; source ~/.bash_profile

Wednesday, January 16, 2019

A TestDriven Workshop Example Using C# and NUnit

I've done this workshop multiple times at work to teach developers Test Driven Development using C# and NUnit.

You can clone it at https://github.com/fincher42/TDDWorkshopNunit.git

The theme of the workshop is from the movie "We Bought A Zoo".

Enjoy and leave me feedback below on how to improve the workshop.


Here's an outline of my notes:

Essence of TDD: Write failing tests **first**, before coding the functionality.

Ping Pong

  1. Bob writes a failing test
  2. Ashley writes just enough functionality in the method so it will pass.
  3. The code may then be refactored to make it cleaner.
  4. Bob and Ashley now switch roles and continue.

This is the Red/Green/Refactor cycle.

One method of arranging your code is to have Arrange/Act/Assert sections in your test.

Benefits of Test Driven Development:

  1. Encourages better architectural design
  2. Makes debugging easier
  3. Guarantees tests are written
  4. Encourages us to think about requirements and edge cases
  5. Let's you be courageous and refactor code

Drawbacks of Test Driven Development:

  1. Tests are expensive. They are expensive to write and more expensive to maintain.
  2. Perfect Unit Tests with 100% coverage do not offer any guarantees on overall code quality. Don't be lulled into a sense of false security.
  3. GUI, Integration, Performance, and Endurance tests are also needed.

Thursday, January 10, 2019

The Four Biggest Changes in Software Development in the Last 40 Years

I was giving a workshop on Test Driven Development today. Being a history nerd (don't get me started about the causes of the fall of the Roman Empire), I was reflecting back on how much has changed in software and how much hasn't. I started programming 42 years ago on punched cards. Here's my list of the most game changing developments in software in the last 40 years.

  1. Duh, It's the Internet
  2. Being able to use Stackoverflow and its kin, we can peruse the minds of thousands of people and find a solution quickly. Online training courses are available to teach us the latest software. It's simply amazing how much more we can create and learn.

  3. Computers are so much faster.
  4. With punched cards at Texas Tech University in the fall of 1976, a diligent student could get in five compile/executes cycles a day. Five. Now you can do that in a few minutes. This changes the way we develop software. Instead of mapping out your entire program on quadral paper using the IBM flowchart template with a Pentel mechanical pencil, we can start programming and build the software iteratively.

  5. Interactive Development Environments (IDE)
  6. Having an IDE that can pop-up all the available methods on an object is such a time saver. Having Resharper to refactor code on the fly, perfectly, is such an asset.

  7. Test Driven Development (TDD)
  8. Test Driven Development encourages us to write software that is easy to test, but more importantly, it demands a layered architecture and encourages small modules. TDD gives us the courage to do massive refactoring. Thank you Kent Beck.

My major professor at Tech use to tell us about a principle of good software engineering, but follow it up with "But, of course, this doesn't matter if you have really good people." That is still true today. The heart of producing good software is excellent people with small egos who have a passion to hone their craft and cooperate with their peers.

Wednesday, November 28, 2018

Retirement Planning and Financial Safety

I gave a presentation recently about saving and Financial Safety.
Here's a link to the slides: prezi.com/p/drbqcvfppehl. Use your right-arrow key to progress through the topics.
Let me know if you have any suggestions.

Wednesday, November 21, 2018

Logitech Mouse Buttons Not Working In Visual Studio 2017

I love my Logitech Dark Field Performance MX mouse, but in Windows 10 using Visual Studio 2017, the buttons won't work.  (Make a sad face with me).

The problem is that the logitech program needs to run with Admin privilege.
To fix:
0. In the System Tray, right click on the "SetPoint" icon and select "exit"
1. In a file browser open "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Logitech\Mouse and Keyboard"
2. Right click on "Mouse and Keyboard Settings" and select "Properties"
3. Select the "Compatibility" tab.
4. In the "Privilege Level" panel, select "Run the program as an Administrator".
5. Select "OK"
6. Restart "Mouse and Keyboard Settings" via the start menu.
7. Enjoy the buttons on your mouse in Visual Studio 2017.


Wednesday, October 10, 2018

Agile Austin - Can Selflessness Lead to Collaboration?

This month's Agile Austin featured Erin Randall from Schwab talking on "How Building a Foundation of Selflessness Can Make You -- and Your Company Successful."

Here's my notes:

30% of collaboration in a company comes from 3-5% of the people.

Psychological Safety
  - Team members need to feel accepted and respected
  - They need the shared belief that the team is safe for interpersonal risk taking

Use words carefully

Victim Consciousness/Whole Body Yes:   "I have to ..." / "I get to ..."

"Be kind and full of love... but have boundaries ..."

Chunk your work to see its impact - do things for an extended period of time, not just a few minutes, to feel the impact.

Make certain to do things that fill you up.

Collin Powell said when the troops stop bringing you problems it's because they think you don't care or they think you can't help.

Erin is a big fan of storycubes.com

Give generously.
Acknowledge help.




Monday, August 27, 2018

Adobe Experience Manager (AEM) Examples and Notes

Personal AEM Notes

I just recently started a project at work using Adobe Experience Manager (AEM). Here's my random, rambling collection of notes. If you know of a better way to do any of these examples please let me know by adding a comment.

Good resources:
  1. Jeff's Youtube series Programmer Vs World AEM Series
  2. HTL guide: https://github.com/Adobe-Marketing-Cloud/htl-spec/blob/master/SPECIFICATION.md#225-test
  3. https://github.com/pankajchhatri/AEM

General Tips for Working with AEM

  1. Save often when creating objects - all the time. Create an object, then "Save All", or Ctl-S. All the time. Delete something? Save immediately.
  2. Remember to always to a hard reload of a browser after changing AEM content, Ctl-Shift-R.
  3. Coming from Visual Studio, I found the IntelliJ "Live Edit" plugin and the Chrome plugin very useful.

Jeff's overview of AEM components:

Apache Felix - osgi framework - forces modular sw development - service orentation
Jackrabbit - JCR content repo, JSR-170,283, workspaces, nodes, properties
Sling - Restful Web Framework
Sencha EXT JS 4 - js application framework
Lucene - search engine
Quartz Scheduler - cron system programmatically accessable
CRX - Tar Journal, Package Manager, deploy and share, Servlet Engine CQSE
CRXDE Lite - ide
WCM (Web Content Manager) - this is what content writers use

Folder Structure

/apps: custom templates, components,
/content: stores all content
/etc: client library, design dialog info
/libs: standard components - do not modify
   example:  /libs/wcm/foundation/components/page/
/conf: All configuration
/var: locks,
/home: info about users and groups
/oak:index: Jackrabbit Oak index definitions

Wierd Strings to Put in the URL

Strings to put after "http://localhost:4502" to do wonderful things:


/cf#/ - sets the old interface, e.g., http://localhost:4502/cf#/content/...
/editor.html/ - uses the new interface, e.g., http://localhost:4502/editor.html/content/...
/crx/de - goes straight to the CRXDE page e.g., http://localhost:4502/crx/de
/welcome - go to the Websites/DAM page e.g., http://localhost:4502/libs/cq/core/content/welcome.html
/siteadmin - go to the Websites e.g., http://localhost:4502/siteadmin
/system/console/bundles - shows versions and the console - e.g., http://localhost:4502/system/console/bundles

How to limit use of a template?

    allowed paths: /content(/.*)? /* anywhere under content */
    allowed paths: /content/sports/baseball  /* only under baseball */

How to get rid of <p>&nbsp;</p>?

Make sure the text you entered into the "text" element does not contain an extra carriage return.

How to only iterate a fixed number of times?

<ul data-sly-list="${thelist}">
    <li data-sly-test="${itemList.index < 4}">${itemList}</li>
</ul>

Set default values with the 'or' operator

  ${properties.pageTitle || properties.jcr:title || resource.name}

How to find what version of AEM you're running

http://localhost:4502/system/console/status-productinfo

To skip the AEM link check

add this class

<a x-cq-linkchecker="skip" href="..." />

Chrome screen creeping up?

In Chrome do you ever get CRX/DE screen creeping up the bottom left panel til it takes over the whole screen? The best solution I've found is to right-click and select "inspect" and make sure the Chrome browser is not in full screen mode.

How to get a list of tags and iterate over them

var categories = [];
var tags = resolver.getResource("/etc/tags/mysection").getChildren();
for (var i=1;i<tags.length;i++) {
   categories.push(tags[i].name);//do something
}

What is a "Client Library"?

It organizes resources that we send to the browser (client side) - things like css and JavaScript.

How to include a resource in a page

<div data-sly-resource="${ 'myname' @ resourceType='wcm/foundation/components/parsys'}"></div>

To show a page title

${properties.jcr:title}

How to include other files

<sly data-sly-include="header.html"></sly>

How to iterate over properties

 <ul data-sly-list.child="${currentPage.getProperties}">
    <li>${child}</li>
 </ul>

 or
 
<ul data-sly-repeat.child="${currentPage.getParent.getProperties}">
    <li>${child}</li>
</ul>

How to place a page property on the HTML page

Here's an example of reading a property from the page dialog in JavaScript and putting the value on the page.

<div data-sly-use.bannerTitle="getBannerTitle.js">
    ${bannerTitle}
</div>
getBannerTitle.js
"use strict";
use(function () {
    return  resourcePage.getProperties().get("bannerTitle");
});

To See the Actual jcr Nodes

/content/....

To show an array as text with a seperator

${['apple', 'pear', 'papaya'] @ join=' - '}
generates
apple - pear - papaya

How to format strings

${'person {0} of {1}' @ format=[7,9]}

How to encode a string for a URL

This will replace non-URL friendly characters like ' ' with '%20'.

  ${properties.jcr:title @ context='uri'}
  or
  ${'This is a test' @ context='uri'}
url:This%20is%20a%20test

How to encode a string for simple html content

This will replace non-URL friendly characters like ' ' with '%20'.

${'Texas A & M University' @ context='text'}
generates
&lt;x&gt;Texas A &amp; M University&lt;/x&gt;  

How to put in an AEM HTL comment

<!--/* This is an example comment that will not appear in the browser. */-->

How to use Sly Element so no "div" element is sent to the browser

Use the "sly" element when you don't want to have the extra "div" element

  <div data-sly-include="head.html"></div>
  /* this produces: <div>myhead.html</div> */
  use only the "sly" tag and the surrounding divs are not created.
  <sly data-sly-include="head.html"></sly>
  /* this produces: myhead.html */

How to replace content of HTML Element

  <div data-sly-text="${currentPage.title}">This will not be seen</div>

Simple Example of "use" to Call Server-side JavaScript and Pass Parameters

For example, suppose we need a social icon component, "sharethis", which will accept two variables, url encode them, and return an object with two url-encoded variables. The returned object is named "site". ( I have since learned the right way to do this is with the "context='uri'"):

  ${'This is a test' @ context='uri'} //url:This%20is%20a%20test

In sharethis.html:

<div class="iconContainer" data-sly-use.site="${'sharethis.js' @ title=currentPage.title, url=request.requestURL.toString}">
    <p class="shareThisTitle">Share this:</p>
    <a href="https://www.facebook.com/sharer/sharer.php?href=${site.url}&title=${site.title}" alt="share on facebook" target="_blank" class="nodecoration">
        <img src="/content/dam/design/facebook.png" title="share on facebook" alt="share on facebook" />
    </a>
...
</div>

The variables passed in are accessed by prefacing them with "this.". In the file sharethis.js:

"use strict";
use(function () {
    return {
        title: encodeURIComponent(this.title),
        url: encodeURIComponent(this.url)
       }
});

To Have AEM Automatically Bundle Css And Javascript Files

clientlib
create node / cq:clientlibraryfolder

create clientlib named zurbfoundation
create property 'categories' string[], zurb.foundation
create property 'dependencies' "+" cq.jquery

js.txt
#base=style   //subdirectory name

css.txt
#base=source

<html data-sly-use.clientlib='/libs/granite/slightly/templates/clientlib.html'>

<sly data-sly-call="${clientlib.css @ categories='zurb.foundation'}" />
<sly data-sly-call="${clientlib.js @ categories='zurb.foundation'}" />
or to do both:
<sly data-sly-call="${clientlib.all @ categories='zurb.foundation'}" />

How to do a REST call to get json objects in server-side JavaScript within a proxy

"use strict";
function geturlcontents(url) {
    //put the following values in a config file 
    var proxyHost = "proxy.district13.gov",
    proxyPort = 80,
    username = "katniss",
    password = "ilovearchery";

    var method = new org.apache.commons.httpclient.methods.GetMethod(url),
    client = new org.apache.commons.httpclient.HttpClient(),
    status = new org.apache.commons.httpclient.HttpStatus(),
    inputStream;

    var hostConfiguration = new org.apache.commons.httpclient.HostConfiguration();
    hostConfiguration.setProxy(proxyHost,proxyPort);
    client.setHostConfiguration(hostConfiguration);

    var credentials = new org.apache.commons.httpclient.UsernamePasswordCredentials(username, password);
    var authScope =   new org.apache.commons.httpclient.auth.AuthScope(proxyHost, proxyPort);
    client.getState().setProxyCredentials(authScope, credentials);

    try {
 var statusCode = client.executeMethod(method);
 if (statusCode == status.SC_OK) {
  inputStream = method.getResponseBodyAsString();
 } else {
  console.log(':::Failed to execute http method. status code = '+statusCode + ' for url '+ url);
 }
    } catch (e) {
       console.log(":::exception: "+e);
    } finally {
       method.releaseConnection();
    }
return inputStream;
};

use(function() {
  var inputStream = geturlcontents(this.api);
  return JSON.parse(inputStream).slice(0, this.maxitems);
});

How to do a REST call to get json objects in server-side in JSP within a proxy


<%@include file="/libs/foundation/global.jsp"%>
<%@page import="org.apache.commons.httpclient.*,
org.apache.commons.httpclient.methods.*,
org.apache.commons.httpclient.params.HttpMethodParams,
org.apache.commons.httpclient.auth.*,
org.slf4j.Logger,
org.slf4j.LoggerFactory,
org.apache.sling.commons.json.*,
java.util.Date,
java.io.*"%>

<%
String proxyHost = "myproxy.mycompany.com";
int proxyPort = 80;
String username = "steven";
String password = "spielburg";
String url = "http://www.omdbapi.com/?t=alien&plot=full";

HttpClient client = new HttpClient();
GetMethod method = new GetMethod(url);
HttpStatus status = new HttpStatus();
HostConfiguration hostConfiguration = new HostConfiguration();

hostConfiguration.setProxy(proxyHost, proxyPort);
client.setHostConfiguration(hostConfiguration);
UsernamePasswordCredentials credentials = new org.apache.commons.httpclient.UsernamePasswordCredentials(username, password);
AuthScope authScope = new AuthScope(proxyHost, proxyPort);
client.getState().setProxyCredentials(authScope, credentials);

String jsonString = "[]";
try {
int statusCode = client.executeMethod(method);
application.log(" *** statusCode : " +statusCode);

if (statusCode != HttpStatus.SC_OK) {
       application.log(" *** Method failed: " + method.getStatusLine());
       throw new Exception(" *** client.executeMethod failed for url "+ url + " with http error code " + statusCode);
}
      // Read the response body.
      byte[] responseBody = method.getResponseBody();
      jsonString = new String(responseBody);
 } catch (HttpException e) {
      application.log(" *** Fatal protocol violation: " + e.getMessage());
      e.printStackTrace();
    } catch (IOException e) {
      application.log(" *** Fatal transport error: " + e.getMessage());
      e.printStackTrace();
    } catch (Exception e) {
      application.log(" *** Fatal error: " + e.getMessage());
      e.printStackTrace();
    } finally {
      method.releaseConnection();
    }  

 JSONArray jsonArray = new JSONArray(jsonString);

String countofmoviesString = (String)properties.get("countofmovies");
int countofmovies = Integer.parseInt(countofmoviesString);

%>
<div class="movieTileContainer">
     <ul class="movieTileList" >
<%
int maxMovies = jsonArray.length() > countofmovies ? countofmovies : jsonArray.length();
for(int i=0;i<maxMovies;i++) {
   JSONObject jsonObject = jsonArray.getJSONObject(i);
    String title = (String)jsonObject.get("title");
    String jurl = (String)jsonObject.get("url");
    JSONObject image = (JSONObject) jsonObject.get("movieEntryImage");
    String thumbnailLocation = (String)image.get("thumbnailLocation");
    JSONArray prices = (JSONArray) jsonObject.get("price");

    String price = (String)prices.getJSONObject(0).get("price");

   %>
            <li class="movieTileListItem">
                <div class="content">
                    <div class="movieTileBox">
                        <a class="movieTileLink" title="<%= title %> " href="https://www.MyMovieSite.com<%= jurl %>">
                            <p class="movieTileTitle"><%= title %> </p>
                            <img class="movieTileImage" width="185" height="101" src="https://www.MyMovieSite.com<%= thumbnailLocation %>"
                                 alt="<%= title %>">
                                     <p class="movieTilePrice" <%= price %>
                            </p>
                        </a>
                    </div>
                </div>
            </li>
<% } %>
    </ul>
</div>

Common Resource Types:

text field: granite/ui/components/coral/foundation/form/textfield

number: /libs/granite/ui/components/foundation/form/numberfield

DAM file: granite/ui/components/foundation/form/pathbrowser

How to lowercase a variable

More generally, how to invoke a JavaScript method on an htl variable. Call the method without parenthesis.

<a href="${myvariable.toLowerCase}/mypage.html">

Important AEM directories

/libs/granite/ui/components/foundation - new components
/libs/wcm/foundation/components/

To Add An Editable Area

<div data-sly-resource="${ 'content' @ resourceType='wcm/foundation/components/parsys'}"></div>

To Show AEM Quickstart Frame

add this immediately after body tag and it will present the AEM quickstart frame

<div data-sly-call="/libs/wcm/core/components/init/init.jsp"></div>

How to Create an Editable Button

/components/materialize-button/dialog/items/items/tab1/items
fieldDescription / What do you want the button to say
fieldLabel / Button Text
jscr:primaryType cq:Widget
name / ./buttontext
xtype / textfield
<a>${properties.buttontext}</a>

Unorganized Snippets of Forgotten Thoughts

on components, "group" is category.
to add dialog: rt-click/create...dialog
on tab1, create a node with name of "items" and type of cq:WidgetCollection
  inside items create another node named "buttontext" of type cq:Widget
  in Properties add "xtype/String/textfield"
                add "fieldDescription/String/What do you want the button to say"
  add "fieldLabel/String/Button Text"
  add "name/String/./buttontext"  --name is where it puts the value

from component:
${properties.buttontext}
mainpage.tidy.4.json

(to get a list of entities, API Documentation/CQ/Ext/form)