Adding Dependencies To The Go Project

In a previous post I wrote that if a language has a standard way of making projects, then that should be taught right away, along with automated tests. Then I wrote a post in which I went over making a simple project with Go.

I realized I skipped something important: adding external dependencies. I will re-use the project from the previous post. You should complete the steps in that post before starting this one.

The project already has two packages. This time I will add two files in one of our existing packages. Each file will use a different module. I will also include a test for each.

I picked a couple of project off of the Awesome Go github page.

The first one is stringy (link to module on pkg.go.dev here).


cd spearhead
emacs morestrings/use_stringy.go

Here is the contents of the file:


package morestrings

import (
    "fmt"
    "github.com/gobeam/stringy"
) 

func UseReplaceLast(root_string, old_s, new_s string ) string {
    fmt.Println("in morestrings/UseReplaceLast")
    replaceLast := stringy.New(root_string)
    return replaceLast.ReplaceLast(old_s, new_s)
}

I am only using the “ReplaceLast” function. Notice the line importing “github.com/gobeam/stringy”.

Next I run “go build”:


go build
morestrings/use_stringy.go:5:2: no required module provides package github.com/gobeam/stringy; to add it:
    go get github.com/gobeam/stringy

I will add code to spearhead.go to invoke my function:


fmt.Println("about to call morestrings.UseReplaceLast('this is my string, working with strings, i love strings', 'string', 'rope') : ", 
        morestrings.UseReplaceLast("this is my string, working with strings, i love strings", "string", "rope"))

Before I run “go get”, here is what is in the go.mod file:


more go.mod 
module info/shelfunit/spearhead

go 1.18

Now I run “go get”:


go get github.com/gobeam/stringy
go: added github.com/gobeam/stringy v0.0.5

Here is go.mod:


module info/shelfunit/spearhead

go 1.18

require github.com/gobeam/stringy v0.0.5 // indirect

There are no issues running “go build” and running the executable:


go build
ericm@latitude:~/github/goapps/spearhead$ ./spearhead 
Hello, world.
about to call numberstuff.AddOneToSum( 5, 6):  12
about to call numberstuff.SubtractOneFromSum( 5, 6 ):  10
about to call numberstuff.AddOneToProduct( 5, 6):  31
about to call numberstuff.SubtractOneFromProduct( 5, 6 ):  29
about to call morestrings.ReturnStringTwice("twice"):  twicetwice
in morestrings/UseReplaceLast
about to call morestrings.UseReplaceLast('this is my string, working with strings, i love strings', 'string', 'rope') :  this is my string, working with strings, i love ropes

The next step is to make a test file: morestrings/use_stringy_test.go


package morestrings

import (
    "fmt"
    "testing"
)

func TestUseReplaceLast(t *testing.T) {
    fmt.Println( "Starting TestUseReplaceLast" )
    cases := []struct {
        root, old, new, want string
    }{
        {"Hello, world, i love the world, dog meets world", "world", "food", "Hello, world, i love the world, dog meets food"},
        {"learning go, will go places, gonna be big",       "go",    "wa",   "learning go, will go places, wanna be big"},
        {"I love life, go live your life, go create life", "life",   "lice", "I love life, go live your life, go create lice"},
    }
    for _, c := range cases {
        fmt.Println( "c.root: ", c.root, ", c.old: ", c.old, ", c.new: ", c.new, ", c.want: ", c.want )
        got := UseReplaceLast(c.root, c.old, c.new)
        if got != c.want {
            t.Errorf("UseReplaceLast(%q, %q, %q) == %q, want %q", c.root, c.old, c.new, got, c.want)
        }
    }
    fmt.Println( "Ending TestUseReplaceLast" ) 
}

When I run “go test -v ./morestrings/” we get all the tests for this module. I will only share the output of the test I just added:


=== RUN   TestUseReplaceLast
Starting TestUseReplaceLast
c.root:  Hello, world, i love the world, dog meets world , c.old:  world , c.new:  food , c.want:  Hello, world, i love the world, dog meets food
in morestrings/UseReplaceLast
c.root:  learning go, will go places, gonna be big , c.old:  go , c.new:  wa , c.want:  learning go, will go places, wanna be big
in morestrings/UseReplaceLast
c.root:  I love life, go live your life, go create life , c.old:  life , c.new:  lice , c.want:  I love life, go live your life, go create lice
in morestrings/UseReplaceLast
Ending TestUseReplaceLast
--- PASS: TestUseReplaceLast (0.00s)

If I run “go test -v ./morestrings/use_stringy_test.go”, I get an error:


# command-line-arguments [command-line-arguments.test]
morestrings/use_stringy_test.go:19:16: undefined: UseReplaceLast
FAIL	command-line-arguments [build failed]
FAIL

I am sure some Golang experts are shaking their heads because I did something wrong. As far as I know, while the “go test” command can run tests using a directory as an argument, it does not work as well when you specify individual files.

To test only the test I just created, I can run this command:


go test -v ./morestrings -run TestUseReplaceLast 

I suppose if you wanted to run multiple tests in a specific file, you would need to give them all a name that is common to the tests in that file, but also unique to that group of tests. So you need to be careful when naming your tests. The argument after the “run” is a regular expression. If I wanted to run the tests from the last post in ./numberstuff/multiplication_enhancements_test.go, I would use this command:


go test -v ./numberstuff/ -run Test.*Product

To run the tests in numberstuff/addition_enhancements_test.go, I would use this command:


go test -v ./numberstuff/ -run Test.*Sum.*

The next package I will use is strutil (link to module on pkg.go.dev here). The file using this module is morestrings/use_strutil.go:


package morestrings

import (
    "fmt"
    "github.com/ozgio/strutil"
) 

func UseCountWords(root_string string ) int {
    fmt.Println("in morestrings/UseCountWords")
    return strutil.CountWords(root_string)
}

Again: note there is an import statement for our module. Here is the output of “go build”:


go build
morestrings/use_strutil.go:5:2: no required module provides package github.com/ozgio/strutil; to add it:
    go get github.com/ozgio/strutil

So I run the “go get” command:


go get github.com/ozgio/strutil
go: added github.com/ozgio/strutil v0.4.0

Now we have two modules in a block in go.mod:


more go.mod 
module info/shelfunit/spearhead

go 1.18

require (
    github.com/gobeam/stringy v0.0.5 // indirect
    github.com/ozgio/strutil v0.4.0 // indirect
)

I will add a couple of calls to our new function in spearhead.go:


fmt.Println("about to call morestrings.UseCountWords('this is my string with words'): ", morestrings.UseCountWords("this is my string with words"))
    root_string := "I am again called upon by the voice of my country to execute the functions of its Chief Magistrate"
    fmt.Println("about to call UseCountWords('I am again called upon by the voice of my country to execute the functions of its Chief Magistrate'): ",
        morestrings.UseCountWords(root_string))

And again I call “go build” and run the executable:


go build
ericm@latitude:~/github/goapps/spearhead$ ./spearhead 
Hello, world.
about to call numberstuff.AddOneToSum( 5, 6):  12
about to call numberstuff.SubtractOneFromSum( 5, 6 ):  10
about to call numberstuff.AddOneToProduct( 5, 6):  31
about to call numberstuff.SubtractOneFromProduct( 5, 6 ):  29
about to call morestrings.ReturnStringTwice("twice"):  twicetwice
in morestrings/UseReplaceLast
about to call morestrings.UseReplaceLast('this is my string, working with strings, i love strings', 'string', 'rope') :  this is my string, working with strings, i love ropes
in morestrings/UseCountWords
about to call morestrings.UseCountWords('this is my string with words'):  6
in morestrings/UseCountWords
about to call UseCountWords('I am again called upon by the voice of my country to execute the functions of its Chief Magistrate'):  19

I will make a test file in morestrings/use_strutil_test.go:


package morestrings

import (
    "fmt"
    "testing"
)

func TestUseCountWords(t *testing.T) {
    fmt.Println( "Starting TestUseCountWords" )
    cases := []struct {
        in_string string
        want int
    }{
        {"Among the vicissitudes incident to life no event could have filled me with greater anxieties than that of which the notification was transmitted by your order, and received on the 14th day of the present month", 36},
        {"I am again called upon by the voice of my country to execute the functions of its Chief Magistrate", 19},
        {"When it was first perceived, in early times, that no middle course for America remained between unlimited submission to a foreign legislature and a total independence of its claims, men of reflection were less apprehensive of danger from the formidable power of fleets and armies they must determine to resist than from those contests and dissensions which would certainly arise concerning the forms of government to be instituted over the whole and over the parts of this extensive country", 79},
    }
    for _, c := range cases {
        fmt.Println( "----- c.in_string: ", c.in_string, ", c.want: ", c.want) // , ", here it is: ", UseCountWords(c.in_string))
        got := UseCountWords(c.in_string)
        if got != c.want {
            t.Errorf("ERROR: UseCountWords(%q) == %d, want %d", c.in_string, got, c.want)
        }
    }
    fmt.Println( "Ending TestUseCountWords" )
}

Here is the result of go test -v ./morestrings -run TestUseCountWords:


=== RUN   TestUseCountWords
Starting TestUseCountWords
----- c.in_string:  Among the vicissitudes incident to life no event could have filled me with greater anxieties than that of which the notification was transmitted by your order, and received on the 14th day of the present month , c.want:  36
in morestrings/UseCountWords
----- c.in_string:  I am again called upon by the voice of my country to execute the functions of its Chief Magistrate , c.want:  19
in morestrings/UseCountWords
----- c.in_string:  When it was first perceived, in early times, that no middle course for America remained between unlimited submission to a foreign legislature and a total independence of its claims, men of reflection were less apprehensive of danger from the formidable power of fleets and armies they must determine to resist than from those contests and dissensions which would certainly arise concerning the forms of government to be instituted over the whole and over the parts of this extensive country , c.want:  79
in morestrings/UseCountWords
Ending TestUseCountWords
--- PASS: TestUseCountWords (0.00s)
PASS
ok  	info/shelfunit/spearhead/morestrings	0.002s

In case you are wondering, while reading through post, what those quotes are, it is my duty to inform you, as any good upstanding citizen would, that they are from the first three inaugural addresses of the heads of government of our great country, whose writing style, which leaves much to be desired by people living in the post-Hemingway era, given that inserting entire thoughts in the middle of sentences can introduce unneeded complexity, I have done my utmost to emulate.

Given the length and content of Washington’s second inaugural address, I get the impression he did not want a second term.

You’re welcome.

Image from Synaxarium of Euthymius of Athos, an 11-century Georgian manuscript, image from Wikimedia, assumed allowed under public domain.

Password Managers Really Could Provide Sufficient Security

BLUF: Increased use of password managers would like to improvements in security for both individuals and businesses, and would make a lot of “post-password” security measures unnecessary.

More use of PMs will not solve all security issues. I do not think we can talk about a site or a database (or anything) as being “secure” or “insecure”. I think it is a matter of degrees. We can only talk about “more secure” or “less secure”. That said, I think password managers would go a long way towards solving a lot of problems. Hopefully it is not too late to make improvements. And I know vendors are trying to push things in a different direction.

I have been listening to old episodes of security podcasts: Security Now and Risky Business. I started at the very beginning for both, and I am up to about 2012 for Security Now and 2013 for Risky Business. I got up to 2011 with Security Now. They said passwords are dead, but I think password managers could solve a lot of issues and improve security. I think if people use them more, we would not need to move to a password-less future. I use KeePassXC. I hope that KeePassXC will still be useful in a world where vendors want to control access.

One is issue with passwords is password reuse. A lot of people re-use passwords because they cannot think of and/or remember new passwords. So if hackers get a database of users for one site, they will try those credentials on other sites, and sometimes get they lucky. With a PM, you only have to remember the password or passphrase for the PM. It can create new passwords for you so you do not have to remember them or re-use them. And if a site has a policy about changing passwords on a regular basis, again you can create new ones easily. One of the times Kevin Mitnick was on Risky Business he said he was trying to get information about his credit card. He had questions about his account, and the woman on the phone said he needed to provide his password. She starting giving him hints because he had trouble remembering. If he had a good password manager, he would have the second password available, and the support desk would not be practicing bad security.

With KeePassXC, you can create attributes which are stored as key/value pairs. You can use these for password reset questions. Many famous people have had credentials hacked since their answers are public information: mother’s maiden name, where were you born, where did you meet your spouse, etc. Much of this information can also be obtained for just about anyone if you know where to look. One way around this is to make answers up. Tell a site you were born in a place you have never been to. Put in a random phrase for the title of your favorite movie. But if you make stuff up, how do you remember what answers you gave for each website? Attributes in KeePassXC can take care of that for you.

You can also attach files to an entry. This would be a good way for people who are not very tech-savvy to send each other sensitive files. Make a database file with one entry and attach your files. Put it on Google Drive or DropBox, and email the link to whoever you want to send it to. Then send them the password or passphrase (I think passphrases are better and should be used whenever possible) some other way. If you send the link to the file in an email, do not email the passphrase. The best thing would be to do it over the phone, and they can type make an entry in their own KeePassXC database and type it in there.

I used to be one of those people who thought what if someone gets your PM? Well, we have seen the alternative. If you have a strong passphrase, I think you will be fine. As Bruce Schneier has pointed out, there is nothing wrong with writing your master password on a piece of paper. The important thing is what do you do with that pice of paper.

Could your PM passphrase be brute-forced? I suppose so. But there are counters or potential weaknesses for just about everything. I think if you take a few intelligent steps to be secure you should be fine. “What if they do A? What if they do B? What if they do C?” That cycle never ends. Nothing is perfect.

I use KeePassXC locally, running as a standalone application. I do not hook it into my browser. I clear cookies when I exit my browsers. I think storing passwords in a browser is a bad idea. As with many things in security, doing something that is more convenient is not always a smart idea.

And I hope I never have to use an online PM. With online PMs you are adding more risks to your threat model. What if their site is offline? Then you cannot log in to anything. Suppose your online PM is down, but your bank, your utility and Netflix are all up. Now you have to wait to pay your bills and watch movies until the PM site is back up. These sites have been breached, particularly LastPass (see here and here). According to this page, just about every PM has been hacked in some way. It mentions KeePass, but not KeePassXC, which is a fork (actually a fork of a now-dead fork) and has a separate source tree. Another issue with online PMs is a lot of them have different tiers of service, and many of them (including the popular ones like 1Password and LastPass) have bumped some features up to a higher tier, leaving some users high and dry.

As to whether or not KeePassXC runs on a phone: I do not care. I do not use my phone for too many things except as an alarm clock, a stop watch, two-factor auth when I have to and ignoring the few calls I get. Most apps are just ways to get you to spend more money. I do not need help spending more money. I need help making more money. And I just hate this phenomenon of people being on their phones all the time and trying to do everything on their phone. I have seen people pull half-way out of parking spaces and stop because they were looking at their phone. I don’t know if phones are making people stupid or giving them an excuse to let their freak flag fly and stop hiding their idiocy, but I am not interested in doing everything on my phone. When I see people at the grocery store walking way too slowly looking at their phones, I am always reminded of that line from Blaise Pascal: Mankind’s problems are due to his inability to sit in a quiet room alone.

Every month I make a copy of my KeePassXC files (as well as other files, including my Org-mode files) onto a couple of USB flash drives. Between KeePassXC and Org-mode I am becoming more disciplined with all my information.

One way to be disciplined is consolidation. One argument against PMs is that they put all your eggs in one basket. True, but it is a basket you can control. We put “all our eggs in one basket” all the time. How many people live their lives on their phone? How many people keep all their physical keys on a keychain? As Troy Hunt pointed out, PMs are not perfect, but they are better than the alternative.

Some people might object to KeePassXC because it is open source. One person on Hacker News argued against open source PMs on legal reasons. He tried to explain KeePassXC to his father (who is a lawyer), and his father was horrified there was “no legal entity to hold accountable”. Either that person’s father is a bought-and-paid-for shill, or really really dumb. If you sue someone (even if they are bigger than you), they can turn a course case into an endurance contest. Control what you can control.

Now a lot of vendors are pushing a “passwordless future”. Vendors cause the problem, then they try to solve the problem. I do not want to give vendors any more control over my life. I do not want to be forced to use a phone, especially a specific phone vendors. I know I am kind of old-school in how I access the web. I use a browser on a laptop. If other people want to go through life not saying if the sun is up until Apple tells them it is, they can do their thing and I can do mine. I do not want vendors having any sort of access to my fingerprint, or my face, or be forced to use anything by Microsoft, or buy a stupid iPhone. I cannot change my face, or change my fingerprint, and I do not want to be tied to a device. Everything I read about this “passwordless future” requires me to do things the way they want me to do it, and not the way I want to do it.

It is odd to me that a lot of people in the US are distrustful of the “guv-ment” and complain about taxes, yet they have no problem doing whatever Microsoft tells them without question. And there are a lot of people who pride themselves on not trusting Microsft, yet will do whatever Apple tells them (and constantly buy overpriced products year after year).

You’re welcome.

Image of David and Goliath from a 9th-century manuscript  Vat. gr. 752 from the Vatican Library; image from Wikimedia, assumed allowed under public domain.

Random Thoughts On Javascript

Random thoughts on Javascript.

As Matthew Butterick put it, Lisp makes me smarter, while anything named *Script kills brain cells on contact.

Here is a comment from Hacker News that sums it up for me: ..they feel like walled gardens of arbitrary knowledge that only applies to their ecosystem rather than to some fundamental learning about software. When I learned about OOP I was able to understand OOP code in a broad range of applications, languages and frameworks, but learning how react works gives me no insight into anything but react, and it’s even abstracted enough from JavaScript that you could learn React without ever properly knowing how to write JavaScript (which is something I’ve encountered in a handful of new devs).

It does seem like a lot of Javascript developers are like small children: They only know Javascript, and cannot imagine anyone not knowing only Javascript. Like iPhone users but worse. They seem to constantly re-invent the wheel, and there seems to be no collective learning. If Javascript is so wonderful, why are there so many libraries, frameworks and entire languages that transpile to Javascript? If Javascript is so wonderful, why do people go through all that effort to avoid dealing with Javascript directly?

Whenever I tell people I want nothing to do with Javascript, I get the same song and dance that “you have to know Javascript.” First off, I do not use it at my current job, so for a lot of jobs you do not. But I do have to use apps made by Microsoft. Because I have to. I am tired of using garbage because I have to. That is one reason I tend not to call in to the Austin Clojure Meetup when they talk about ClojureScript. Lisp is something I want to learn. I spend enough time with things I have to use. Don’t pollute the stuff I want to use with the stuff I have to use.

And usually you get to the first stage of “you have to use X” because a lot of people are too lazy or too stupid to investigate alternatives. The second stage is the X that you have to use is the only alternative, and most people are too lazy or too stupid to know there ever was an alternative. If I wanted to do what everybody else does, I would not be interested in Lisp or Clojure. You use Lisp because you know the world is wrong.

Maybe everybody else uses it because everybody else is stupid. JS is like Windows: It is a status quo that everybody defends, nobody actually chose, and very few actually like.

I don’t buy the argument that developers should learn Javascript because it is a combination of Lisp (the good parts) and C (everything else). “It has the stuff you like with the stuff you do not like.” I would like my life to have more of the stuff that I like, and less of the stuff I do not like, not to mix them together. “It’s Lisp and C” is really a reason to learn Lisp.

I am tired of being treated like a dog, and people thinking that I will just eat whatever is put in front of me.

But I am not the only one. The README for Coast states “It uses a relational database and renders html on the server without javascript which allows you to ship your web applications faster.” The Pragmatic Bookshelf has a book called Programming Phoenix LiveView: Interactive Elixir Web Programming Without Writing Any JavaScript. Granted, they do not seem to be against JS. I think that LiveView is like GWT: You write code in Elixir (LiveView) or Java (GWT), and it gets translated to JS. Because JS is too complicated.

The PDFs for that book said that we need JS to make single-page apps and give users all the “modern” features of the web: like notifications and infinite scroll. Personally, I need fewer notifications and I hate infinite scroll. JS seems to give nothing but bloat. Granted, there are some things it is useful for: I think a lot of video players are done with JS. But beyond that, all JS has given us is bloat and complexity. I feel like I am spending more and more time on websites waiting for circles or rings to stop spinning.

I think we need to get back to CRUD apps. The kind we used to make 10 years ago. Yes, you had to know several languages, like HTML, CSS, SQL, maybe some Javascript. But you could focus on a language that interested you, like Java, or Ruby, or Python. Now it seems like a lot of people want to make it all Javascript all the time, now it’s Javascript AND maybe a little bit of the thing you really wanted to learn. Two years ago I took a course on Pluralsight about making web services in Go. The course included an Angular app to view the database. The Angular app takes up 589 megabytes on my hard drive. I took the course to learn how to use Go, not deal with Javascript. It reminds me of Joe Armstrong’s line about OOP: I just wanted a banana, not the monkey holding the banana and the tree it is sitting in.

Why they did not have a prerequisite course about making a web application in Go is beyond me.

Javascript is like someone comes to a restaurant, and at first they seem outgoing and charismatic. Then you realize the guy is groping all the women, he’s hammered and you can’t get rid of him.

I haven’t gotten around to reading any of the PDFs I have going over the history of Lisp. Perhaps for a couple of decades the Lisp world was total chaos like JS is today. But now it isn’t. Why not stand on the shoulders of giants?

If my impression of Javascript is out of date, so be it. It wasn’t my idea to ignore history and push a language which was described by its own creator as having “a lot of stupid in it.” He is still jerking around the world by giving us a browser that shields you from ads so they can give you their ads. And if that isn’t shady enough, Brave is involved with corrupt-o-currency. This guy is the poster jerk for crank magnetism.

I am open to learning new things. Lisp. Go. Elixir. Functional programming. Graph databases. I probably need to learn more about relational databases. Just using Emacs will help you to pick up new things: Org mode, CIDER. I learned some Scheme and Racket and how to get them working in Emacs so I could go through Simply Scheme so I could eventually go through SICP.

I have noticed that when people judge you for not being open to new ideas or learning something new, what they are really doing is being judgemental because you are not interested in what they are interested in. Being open to new ideas does not mean being open to all ideas.

You’re welcome.

Image from the Melisende Psalter, a 12th century manuscript assumed to have been created at the Monastery of the Holy Sepulchre; housed in the British Library as Egerton MS 1139, assumed allowed under Public Domain.

Notes On A Drupal Meetup And Estimates

Recently I went to the Austin Drupal Meetup. The topic was “What is this estimation thing? Why “no estimation” is not as crazy as it sounds“. The speaker was Michael Godeck.

Before the presentation, I did talk to someone about Drupal and Gutenberg. He said that right now Drupal uses the CKEditor. It recently got re-written from the ground up, and the new version has not been integrated with Drupal yet. He said that the Drupal community looked at Gutenberg, and saw that there was a lot of WordPress-specific code, so most people decided that Gutenberg was not the direction they wanted to go in.

However, some people kept going, and have ported Gutenberg to Drupal, or re-worked it to work with Drupal. He said that they will demo their results at the next DrupalEurope in September. I think he was referring to this presentation. So, Gutenberg in Drupal is not a sure thing. But if the demo in Europe shows promise, it might happen.

The main presentation was about estimations. He will be presenting at DrupalEurope.

One issue with estimation is that estimates are sometimes interpreted by managers as promises.

He talked about On the Theory of Scales of Measurement by S.S. Stevens which covers different types of measurement. One type is ordinal, which allows ranking, but no meaningful calculation. You can rank movies using a star-based system; usually people go up to four. We know that a four-star is better than a three-star, and a three-star is better than a two-star. But is the difference between a four-star and a three-star the same as the difference between a three-star and a two-star?

Another type is interval, which does allow you to know the differences between quantities. Think of things like time, temperature and distance.

He said one issue with some agile estimation strategies is that the numbers people give are really ordinal, but they are treated as interval. People think that all uses of numbers are the same, but that is not the case. The agile community still seems to be struggling to this day with the question as to whether or not a point is equal to some unit of time.

He also spoke of confidence intervals. It may be time to brush up on statistics.

He also mentioned Thomas Bayes and Claude Shannon.

Image from “Evangelia quattuor [Évangiles dits de François II] (1r-186r). Capitulare evangeliorum (187r-199v)”, a 9th century manuscript housed at the Bibliothèque nationale de France. Source gallica.bnf.fr / BnF; image assumed allowed under Fair Use.

Reasons I Do Not Like Sharepoint

Here are some reasons I do not like Sharepoint.

First off, I think the underlying concept is wrong. Putting office files in on the web is just stupid.

The web started out as HTML files; even dynamic sites make HTML files. Trying to make the web into a viewer for Office files adds a layer of friction. It is also vendor lock-in. The web was intended to be open. And again, MS is trying to close it.

Speaking of files adding friction to the web: I also do not like PDFs on the web, especially multi-column PDFs.

Second: A lot of the files on Sharepoint are Word files, and a lot of the things in Word files do not need to be in Word files. HTML would work just as well. Why are people putting stuff in Word files anyway? (Spreadsheets are another story.) Why not just use some kind of wiki? Or Atlassian Confluence? Or Drupal? Or Intranet DASHBOARD? Or Jive? Or MindTouch? Or anything on this list? (I think this list is a bit more up to date, but unordered.) WYSIWYG editors are not that hard to learn. Why pay for MS Word when you are not using all of its features? And yes, I know SP has a wiki. I have never tried it, and I have no desire to. It is probably terrible. SP is about trying to make proprietary Office files relevant in an open web-centered world. Making a decent wiki with SP would expose the absurdity of SP’s existence. Making proprietary Office files relevant in an open web-centered world is Microsoft’s problem. Not mine, and not yours either.

If you really need to print, I am sure there are other systems that can convert content to PDFs. There are systems that have single sign-on capabilities.

If you use files, why are you using an online system? The impedance mismatch causes problems. People still download the files and email them to each other and get out sync. And even though there is versioning, people will manually add different versions of files. I have seen files in folders like this: fileX.doc, fileX_002.doc, fileX_DECEMBER.doc. If you are going to put stuff in Sharepoint, I want to look at a folder and just see the files I need to see. Don’t make me figure out whether I should look at fileX, or fileX_002, or fileX_DECEMBER.
I think this is because SP tries to do so many things.

Another reason is almost everyone hates it. At least, almost everyone I have asked about it at companies where I have worked that have used SP have hated it. Maybe everybody tells the big shots they love it and everybody is lying to me, but I really do not have any decision-making authority. Why would people lie to me?

There are many developers who take a course that uses Lisp or Scheme, or get a job using Lisp, and they will rave about it years or even decades later. They will say that Lisp/Scheme changed their perception unlike anything else. That they learned more by using Lisp than they learned using anything else. Nobody really holds MS technologies in the same esteem. Does anyone ever look back years later, and say, “God, what a great piece of engineering ${SOME_MS_PRODUCT} was. I learned so much using ${SOME_MS_PRODUCT}”. A lot of non-technical people love MS products because they are generally unaware of any alternative. We should use technologies that we admire, not use technologies simply due to inertia or ignorance.

We are always told on the technology side that we have to “learn to understand the needs of the business.” Why don’t they have to learn anything about technology? Or what is good technology?

The only people who seem to like SP are managers and SP consultants. I asked someone at my current employer why we used SP, and he told me that we got a good deal from our cloud provider. Not that we need it. Or that it is good at its intended purpose (whatever that is).

I have found that many things that are justified based on cost and not quality are usually not very good. When I was at BofA, we had to use some computer-based training. Everybody hated it, except our finance guy. When he was asked to justify it at a meeting, he said it was “cost-effective.” If the users hate it and nobody learns anything from it, how is it effective?

Another reason is that it is from MS. It’s the same old bait and switch. They sell it as something easy, and you don’t need an admin. But when you hit a wall, or want to do something advanced, then MS says you need an admin.

Some people have this weird blindness about MS. If you present them with another spreadsheet or word processor, they will reject it because it is not exactly like MS Office. But if MS changes the interface (like from a toolbar to a ribbon), people just go along with it.

Another reason is that the search capabilities in SP are terrible. This is important for something used to store documents. I have always gotten better search results on blogs and wikis. Content on wikis can be versioned, so why put stuff into SP? I think most businesses could replace SP with a wiki. I think a lot of wikis can do single-sign on, permissions, whatever. Bookmarks would not change. A lot of people love to move SP folders.

SP is a complex product sold as a simple product. It is a desert topping and a floor wax. If SP does not fit your business, you have two choices: change your life to fit SP, or replace SP. Desktop PCs, laptops, cel phones induced people to change their behavior and workflow. SP is not amazing enough for people to want to change for it.

At my current employer, search is so bad that a committee was started to come up with solutions. I went to one meeting, and I realized it was a waste of time. Someone suggested a SP site with links to all the other SP sites. For some reason, dropping SP was not considered. I do not get the hold SP has on some people. Yes, migrating would be expensive. But using it is expensive. And painful.

complex product sold as a simple product
impedance mismatch
vendor lock-in
bad search

You’re welcome.

Image from Reichenauer Evangelistar, an 11th century manuscript housed at the Bavarian State Library, webpage information here, image from World Document Library, image assumed allowed under CC BY-NC-SA 4.0.

Drupal Update

I have started going to some of the Chicago Drupal Meetups. I tried Drupal before and dropped it. I started going to the meetups because I want to expand my portfolio.

One of the reasons that I dropped it is that there is not rich text editor out of the box in Drupal. WordPress has a rich text editor out of the box. I think it is TinyMCE. For Drupal, you have to install the WYSIWYG module, and THEN go and get the files for one of the supported editors. I am not clear why they did this, but to me it seems like bad design. If I want one thing, don’t make me do something else first. I can get up and running on WordPress much more quickly.

Someone at the last Chicago Drupal meeting said something that is making me rethink Drupal. He said if you know you want a blog, you should go with WordPress. If you know you want a wiki, go with MediaWiki (the software behind WikiPedia). But if you want a web site that can do a lot of things really well, then you should go with Drupal. He did not try to pass Drupal off as the best at everything. Or even the best at anything. But if your site changes (and it probably will) then you should go with Drupal. It can handle the most types of content and site structures and paradigms of any of the content management systems out there.

Image from Wikimedia, assumed allowed under Fair Use. Image from the Vatican Virgil, a 5th century manuscript of poems by Virgil.