Category Archives: Software Development

So many choices, Part 2

Yesterday, I lamented that web development hadn’t come to any consensus on tooling. programming language, basic UI framework or anything else.

I was talking about front-end development, but it’s true on the back-end as well.

Here, I’m not so sure if we could ever get consensus. On the front-end everyone is running in a browser and ultimately has to provide HTML, CSS, and Javascript. I was hoping that would have driven the industry towards one obvious choice.

On the back-end, everyone has been using their tool of choice for decades, and using Javascript (via node) is a good choice now, but it’s not close to universal. And if you are only working on the backend there isn’t a requirement to know Javascript at all, so there are lots of teams that don’t care about matching languages.

For me, using one language on both the front-end and back-end is such a compelling benefit, that I’ve moved to node for anything new. In practice, I haven’t had much code sharing, but I am flipping back and forth so much while developing, that just having to have one language in my brain is reason enough.

And since I use GraphQL, again Apollo is an obvious choice.

Before this, I was using Django and Python for my backends, and I like working with an ORM for SQL data, so I decided on TypeORM. Here there seemed to be 1 or 2 other viable options as well. TypeORM can be DB engine agnostic (depending on what you use), so setting up an in-memory, sqlite version for unit testing is pretty easy.

With Apollo and TypeORM, TypeGraphQL is a nice addition. It lets me have a DSL that describes entities in one place that generates my DDL, queries and also encodes them for GQL/Apollo automatically. If you don’t do this, a lot of your GQL code isn’t going to be type-checked.

My backend is essentially just a DB with GQL in front of it right now, so there isn’t much else to decide. Since I use the same language as my front-end, I can use eslint, prettier, and jest here as well.

The one thing I miss from Django is the automatic admin console and user management. In the end, I do think my admin interface needs to be more custom, but it’s useful at the start until you get around to making a real one. I looked at AdminJS, but unfortunately I had already committed to some TypeORM choices that it couldn’t support. If I thought I’d be on AdminJS long-term, I might have backed out of those choices.

In any case, the choices on the back-end mostly depend on what language you choose. As an iOS developer, I never really had the option of using one language for the full stack—I usually want to make native apps and Swift isn’t ready for the server-side in my view. It’s nice to have this option, and would make me reconsider ReactNative if I need a mobile app for this project.

So many choices

Up until about March this year, I was primarily an iOS developer and had been for a while. But, this year I decided that the things I want to build would be best built on the web, and so I started to learn modern web development. I was struck by the lack of consensus about what that means.

My goal is to build a real web app, not just to learn. I already know HTML/CSS/JS going into this. If your goal is to get started or just to learn, I’d start with HTML/CSS/JS and maybe React or Vue and not worry too much about the rest yet.

Right now, I’d say, if you want to be an iOS developer, you download Xcode, write in Swift, use UIKit for the UI and standard components and libraries and you can build professional apps. There’s built-in support for most things that you need, and the Apple implementations are excellent. All of the apps I have worked on are not much more than this.

On the web, I’d say the one consensus choice is to use VSCode, but then it starts bifurcating quickly after that.

The default language of the web is Javascript, but you can use anything that transpiles to it. I have decided on Typescript, but I think Clojurescript is a reasonable choice. There are probably a few others.

At this point, you basically have nothing. The browser provides an HTML renderer, very basic components, and a limited library. You are going to need to add dependencies to do anything beyond the basics (you had to do this even to get Typescript).

The first choice I had to make was what UI framework to use. I chose React, but people I trust also use Vue. There are few others that seem reasonable, but React seemed a good fit for me. By the way, if you want to get started with React, I recommend Pure React, which is a book explains React in isolation.

It might be overkill, but I decided to use Redux to manage state. React has something built in now, but I like things that have been around a while.

I also needed a design system — something with ready-made components. I didn’t find anything that great, but chose Material-UI in the end as it seemed the best supported.

I wanted to like Microsoft’s Fluid, but I couldn’t get it to look right for me. I also could not get Ant to work at all (I’m a newb at this). Every big company seems to promote one of these — my old employer, Atlassian, has ADG, which looks ok. SalesForce has one too. But, they all seem to have a different idea about what a reasonable amount of markup is for default usage. Material-UI is usually a simple tag with a few attributes to get something on the screen — these other systems are way more complex. There is also a vibrant commercial market for components. I will probably revisit this after my MVP is done.

I decided on GraphQL as my API basis, and so I got another easy choice: Apollo. I also added GraphQL codegen because it can turn GQL into a Typescript API (with typechecking).

It doesn’t stop there. I have eslint, prettier, and jest as my code quality tools. I think those are default choices, but there were others. In iOS, code formatting and unit testing are built in.

And this is all just to get something minimal working. I have also had to add in some other components for specific features.

I have also checked in with people in my network that do this for a living, and I haven’t found two that have made the same choices. Except for VSCode — that does seem universal.

Tomorrow, I’ll talk about the backend, but there is no comparison with iOS, since you’d have to decide on this as well for a server backed app.

Outcome Story Templates

In yesterday’s post about Outcome Stories, I don’t think I quite got the story right.

I suggested changing the story from “As a writer, I want to publish posts, so I can share it with readers.” to “To get readers, a post must first be published.” I do think this does put more emphasis on the goal because it’s the first few words of the story.

But, it would be better if it were the subject of the sentence. The subject is what we’re talking about, and in my fix, we’re talking about the post, not the outcome.

So, tweaking it more, you could say “Getting readers requires that the post is published.” Maybe this is semantics. The more important thing is that the goal is early in the sentence, but if it can also be the subject, it will carry more weight.

But, if we go down this route, maybe we can develop a template around it

  • [Outcome] requires [the object] to [have a state]
  • [Outcome] requires [the persona] to [do an action] to [an object]
  • [Outcome] requires [the persona] to [do an action] to [an object] when [a trigger happens]

So, we end up with: “Getting readers requires the author to publish the post when they are done writing it.”

And again we’re clear that this is necessary, but not sufficient to accomplish the goal.

Outcome Stories

User Stories are centered around the user persona, which seems like a good idea, but it would be better if they were centered on a business outcome.

Consider the Publish button in WordPress.

One way to write a specification for this is to mock that screenshot I pasted above in Figma and say what the button does when clicked. Perhaps you’d use the typical User Story format and add “As a writer, I want to publish posts, so I can share it with readers.”

That works well in the sense that the production software will probably do what was specified. But, we’ve lost an opportunity. The story is focussed on a persona, but doesn’t emphasize the goal. I’m not even sure the persona matters at all here.

And just like no one wants a drill, I don’t want to publish. I want to influence readers. Others might want ad revenue or newsletter subscribers or to sell books. So, can we take the opportunity in this story to remind everyone about the business goals? The final state is not a published post.

It seems like a small tweak, but I’d word it “To get readers, a post must first be published.”

And now it’s obvious that this is insufficient. Yes, we need a Publish button, but that won’t accomplish the goal. This wording begs for more features to support the actual goal. It also implies that the metric for the success of the Publish button is the number of readers not (for example) the number of published posts. How would the design of publishing in WordPress be different if it was centered around the business goal of the users?

Publishing should lead directly to distribution, but in actual WordPress, the end of the publish step is a button to copy the link.

I guess I’ll go tweet it myself.

An Unnamed Programmer in Peopleware is One of my Heroes

I read Peopleware early in my career and revisit it every few years. Yesterday I wrote about what they meant about 10x programmers, and while doing that, I looked for this excerpt, which I think about all of the time (emphasis mine).

One of the upper managers buttonholed me to request that I assess […] his project staff. He was particularly curious about one woman. It was obvious he had his doubts about her: “I don’t quite see what she adds to a project; she’s not a great developer or tester or much of anything.”

With a little investigation, I turned up this intriguing fact: During her 12 years at the company, the woman in question had never worked on a project that had been anything other than a huge success. It wasn’t obvious what she was adding, but projects always succeeded when she was around. After watching her in class for a week and talking to some of her co-workers, I came to the conclusion that she was a superb catalyst. Teams naturally jelled better when she was there. She helped people communicate with each other and get along. Projects were more fun when she was part of them.

Peopleware

They go on to say “The catalyst is important because the project is always in a state of flux. Someone who can help a project to jell is worth two people who just do work.”

I don’t know who she was, but this programmer was one of the most influential role models of my career. I constantly ask myself what would she do. My post about How Senior Software Developers Think is my take on it, but it’s much more than that. Coding is certainly an important part of being a software engineer, but most projects can technically be done by a wide range of coders. The other skills, the work that makes the project succeed, are a lot more rare in my experience.

Waterfall is a Myth

I think everyone who programs has heard the story of the failure of the waterfall process.

Back in the olden days, to build software someone would first write up a document with all of the requirements. Then, the software architects would design a system and produce a document with that. And, then, I guess there would be some kind of implementation plan and that would be completed. Then, the programmers would code it up. And finally, the testers would test it. Then, you ship it.

It looked like this:

I’m going to say that I think this never happened in real life. I doubt anyone seriously tried it for anything big. Or, if they did, I hope they failed super-fast and started over.

This diagram comes from a 1970 paper called Managing the Development of Large Software Systems by Dr. Winston Royce. Right after this figure, he says: “I believe in this concept, but the implementation described above is risky and invites failure.”

Then he goes through a bunch of fixes to the process and ends up with:

The process as described seems completely reasonable to me (see the original paper) . It features

  • Code review
  • Automated tests
  • DevOps manuals
  • The idea of a spike implementation to learn and de-risk the real one
  • Including Customers in the process (every circle icon in the figure)

So, even in 1970, it was known that waterfall could never work, and the term was only coined later to describe Royce’s first diagram, which he had immediately rejected.

I think waterfall only really existed as a concept to immediately reject and fix, not a serious suggestion for what to do for a large software project.

Green, Refactor, Red

I’ve been doing more TDD lately (which is why I’ve been watching TDD debates), and one thing that’s been good is to not do Red, Green, Refactor, but instead do Green, Refactor, Red and end the day on Red.

That way, when I start the day, I can warm up quickly by fixing that test and before I know it, I’m done.

I do end the PR on the Green though.

Confession: I Estimate Using Time

I know, I know. I’m supposed to be estimating using Fibonacci story points, and like Whose Line, the points don’t mean anything, but I have tried it, and I don’t get it.

For one, regular people just translate that to some notion of time anyway, and in that regard, I am very regular. If you are going to take some random number I provide and assign a date to it, I’d much rather I do the translation for you.

Also, I feel like a wrong point estimate is never acknowledged as wrong. It’s just that we didn’t do as many points this sprint as we thought we would. A time estimate is more checkable and less subjective. You can track it using normal means. When I work for two hours on something, that’s two hours. How many points did I just work?

If I say it takes 8 hours and after 4 hours, I say that there’s 6 hours left, I have good feedback on my estimate. If I say something takes 8 points and at the end of the day, I think I’m halfway done, was I right? I don’t think you can make any inferences about the correctness of point estimates without some kind of translation to time, and if you do that, then just use time.

If you love and use story points, that’s great. My only strongly held belief is that people should do what works for them. But, it’s not how I think of how long things take.

Tradeoffs in Unit Testing

In this TDD video I linked to, Ian Cooper mentioned that there were a series of videos where Kent Beck, DHH, and Martin Fowler debated TDD and related practices. The first one is here, and there are several more that you can see linked from that one. There are six in total—each about 30 minutes long. The debates were sparked by DHH’s blog that TDD was dead.

One interesting thread throughout is the idea of tradeoffs, and that nothing is necessarily always good or always bad. I had written this before in the context of technical debt and personal savings rate.

In these debates, they discussed whether more testing was always better and whether faster tests were always better. And of course, the answer is: it depends.

With no (or low) tradeoff cost, then yes, more and faster tests are better. If I can make tests faster with just hardware upgrades, then that’s great. Also, when benefits are very high, then even higher costs may seem low. For example, if tests take an hour, then we are willing to bear high costs to make it a few minutes. We would bear some lesser cost to make it a few seconds. But, should we keep going?

I think this all fairly obvious, but in the heat of discussion, it’s often glossed over.

(I should say that I believe for lots of kinds of problems, testing and coding together, whether it’s TDD or or not, makes you go faster and more correctly. I also mostly don’t care about unit isolation if it gets in the way—if you aren’t going faster and more correctly with tests, then I’d start wondering why and whether they might be getting in the way).

WWDC 2021: Summer Plans

So far I’ve only had time to watch the various Swift updates. I wrote about async/await the other day, and I will spend some time later this summer thinking about Sprint-o-Mat’s asynchronous code.

Pretty much the entire app is reactive to asynchronous events, the workout progression, the passage of time, the changing location, and health metrics all come in via delegates and callbacks. I publish those to the UI via Combine. That might still be the best way as we’re dealing with a sequence of asynchronous values, but filling them up may be simpler with the new APIs. I’m not sure yet if this is a use-case for the new AsyncSequence.

I will certainly support the always-on screen—mostly I need to make sure to slow updates to one per second when dimmed. I might also alter the UI in this state to simplify it.

I also saw that there’s a MusicKit now and I’ve been wanting to bring music into Sprint-o-Mat for a while. I already support an in-app media player, but I’ve been wanting automatic music changes during sprints and rests.

One thing I’ve been interested in exploring is communication to an iPhone app. I want Sprint-o-Mat to stay an independent watch app. I am looking for ways for it to communicate to an iPhone app that is perhaps in the same group, but not necessarily in the same bundle. I don’t think there’s anything new here, but there are some watch connectivity sessions, so I have to check those out.