jducoeur: (Default)

(Yeah, I know, I'm still completely failing to diarize beyond hot takes on Mastodon. This makes me sad, but I'm torn in too many directions at once these days. But here's at least what has been chewing up a lot of my time and attention. Cross-posted to all of my blogs, since they mostly have separate audiences.)


Early this year, I started to realize that the inevitable moment had arrived: the frontier LLMs no longer suck at writing code. So after a couple of years of largely ignoring the hype wave, it was time to knuckle down and learn how to use them for that purpose.

Mind, I've been using them for research for years -- Kagi Assistant is very much my friend, and I use it several times a day.

(I don't use them for writing: I care too much about my personal "voice". All this em-dash and parenthesis abuse comes from my own Gen X, OG Internet style -- I'm the guy the LLMs learned all that from. Sorry.)

The early LLMs wrote such bad code that it wasn't worth my time to even really kick the tires much, but Claude Opus and GPT Codex are now able to write decent Scala code -- not fabulous, but good enough to actually be a net plus.

I've been using them hard for a couple of months now, so let's talk about that. Nothing here is revolutionary -- it's just an anecdotal report from someone who has been programming for 50 years, in many paradigms, environments and languages, about what this next paradigm is like.

For context, I'm using Claude Code (mostly Opus) for Querki, and GitHub Copilot (mostly on top of Claude Opus and GPT Codex) at work.

(Note: yes, yes, the AI Industry is mostly staggeringly evil, and likely to collapse under the weight of its nonsensical economics sometime soon. Let's take that as read, and not get derailed by it too much in this post. If folks want to engage in meaningful discussion about the downsides in comments that's fine, but I'm not impressed by extremist arguments on either the pro or con sides: it's a complex and subtle set of topics.)


There's a lot of exaggeration being spouted in terms of the quality of the output, with some people saying it's all terrible crap and others saying "fire all the engineers, the LLM is enough". The reality seems to be somewhere smack in the middle.

I'm using the LLMs both for greenfield development (I've been booting up a new microservice at work), and legacy work (notably Querki, whose codebase is ancient and creaky, and needs a lot of TLC). It's been particularly useful for cross-repo development: for example, lifting code out of a service and moving it into a library -- that's traditionally a pain, but is proving pretty easy this way.

I can get very good results from the current-generation models, but that doesn't happen magically. I've been putting a fair amount of effort into building up AGENTS.md files (which is how you give generalized instructions to the LLM about how to behave in this code), and a lot of effort into each prompt.

People talk a lot about "vibe-coding": give the LLM a minimal prompt, and just YOLO the results. Far as I can tell, that's still a terrible idea for serious, long-lived code bases -- the things just don't produce very good code when left to their own devices.

(Long-lived code needs to be well-designed and well-factored. That's more important in the brave new world of AI, not less, because badly-written code is going to cost more to maintain in the long run, just in terms of the number of tokens you have to shove around and the amount of reasoning effort needed by the agentic LLMs. So leave the vibe-coding for throwaway projects and prototypes.)

Yes, LLMs might eventually get to the point of producing genuinely good code without much oversight; frighteningly, "eventually" might well be within the next few years. But we're not there yet.

So in practice, I'm typically spending a bunch of time preparing for each PR ("pull request" -- basically a unit of work in modern programming). I make sure I understand the problem decently well, and write up a deeply-detailed prompt: typically a couple of paragraphs, and a bullet list of the key things I want to make sure it deals with, usually with some specifics about how the code should be factored.

Paired with that is the all-important "don't trust the AI" for the outputs. The code tends to look good, in the same way that chatting with an LLM sounds human-like, but it's prone to similar problems of being over-confident and weak on the details.

So in practice, I do a detailed code review of the output, even before I open the PR. I'll often tell the LLM to restructure it in various ways, to clean up the code paths so that everything is tighter and easier to maintain.

This is where it is critically important not to anthropomorphize the thing. If this was a human, I might well be tempted to softball it: to not hassle them too much about details, lest I burn out an engineer. But these aren't people (ignore the chirpy obsequiousness), and politely but firmly bossing them around is how you get the best results.

A key point here: using LLMs effectively and responsibly requires critical thinking. A lot of critical thinking. We've never been collectively all that good about teaching that in school, and I worry quite a lot that this is one of the ways in which that is going to bite society in the ass.

Anyway, at the end I often have another LLM pass to do its own critical review of the code. That's generally bad at finding maintainability problems, and they're horribly prone to whining about picky details that don't actually matter, but they do fairly often pick up on bugs that are worth fixing.


Now let's talk about productivity.

There was a lot of hype a while back about a study showing the LLM usage wound up making programmers less productive, not more. I recommend ignoring that: it was a fairly narrow study, as far as I could tell, largely about testing using LLMs badly, in a very specific and naive way -- of course that produced bad results. I don't think it matches what you get when you use the things mindfully and carefully.

The key thing, I'm finding, is to separate "designing" from "typing". I'm still doing all of the high-level designing, and most of the detailed design, myself. But for PRs of any serious size, I'm letting the LLM do most of the actual typing. That's a pretty serious speedup, provided that most of that typing is correct -- which at this point it mostly is when using the best models, carefully-steered.

It's by no means instantaneous, mind: those detailed prompts typically take me half an hour or more to craft. But I usually do all that planning anyway, and being forced to write down the plan in advance isn't a bad thing. And that's followed by 2-20 minutes of the LLM cranking away, often replacing what would have taken me a day of type, compile, type, compile, type, compile, test. (Rinse, lather, repeat.)

Anecdotally, my sense is that my overall coding productivity is getting boosted three-to-five-fold. That's not a small thing, especially given that I'm not a slow programmer to begin with. I'm cranking through tickets significantly faster than I traditionally could, and I'm using enough care that I don't believe quality is suffering.

That said, it's not magic. It does require attention and time if you want great results -- I suspect that a five-fold speedup is probably somewhere around the cap without sacrificing quality, at least until and unless the LLMs are genuinely good enough to operate unattended.

And mind, coding is only a fraction a senior engineer's workday. Most of my time is spent dealing with higher-level product architecture and design, research, problem analysis, and of course meetings and discussions in chat. LLMs can help a bit there as well (Kagi Assistant in Research mode has enormously sped up the technical-research side for me), but there are limits.

So overall, that's a major speedup for a fraction of my job; the total speedup is necessarily smaller. Too many people forget to do that math properly, and expect unrealistic miracles.

And of course, this stuff costs actual money. It's been effectively-free up until now, but with quota limits that I often bump my head against, stopping my work for a time. GitHub Copilot is especially egregious here, with a one-month quota granularity: if you overuse the LLMs at the beginning of the month, you can be dead in the water for the rest of it unless overages are authorized.

But those "effectively-free" prices have been mostly a over-the-top loss leader by the LLM companies, which have been blitzscaling to a degree we've never seen before, burning a bonfire of cash in order to attract market share. I believe we're nearing the end of that, and we're starting to see more-realistic pricing creeping in.

So I expect the cost of LLM-driven programming to rise by an order of magnitude or more in the coming months. I believe that's still going to be a good deal when you factor in the realistic productivity benefits, but it's going to be enough that the bean-counters at many companies are going to get cranky about it, and with good reason. Folks are going to have to start budgeting realistically and appropriately around it (along with training engineers in how to use it well), and just using it profligately for fun is going to become less of a thing.


Anyway, that's my initial take. It's a powerful tool, and a generally beneficial one for programming if you use it responsibly. IMO any serious programmer should be kicking the tires and learning how to use it, or you're going to be in danger of being left behind. (Which happens with every major paradigm shift in this industry -- if you don't keep up with the times, you can easily find yourself unemployable.)

As a side-note: all of this has left me doubling down on my long-held assertion that Scala is the best current programming language for most business use cases. (Rust is probably the best language for the rest of them.) The rise of LLM-driven programming is making that more true, not less: Scala's strengths nicely complement the needs of LLMs. But I've talked enough here, so I'll leave that for my next post...

Never stop

May. 15th, 2025 11:09 am
jducoeur: (Default)

(Posted this on LinkedIn, of all places, since it seems appropriate there. But let's also put it here, where my friends will actually see it.)

I was chatting yesterday with a sometime colleague -- a fellow programmer -- who just got laid off, who asked (paraphrasing) "How do you manage to stay hopeful in this terrible job market? What do you do in the meantime that helps?" Here are some thoughts on that.

Part of my response here is history, because I've kind of lived through it before. 2025 is starting to remind me of 2002 -- what we referred to at the time as the "nuclear winter" of the software industry, in the wake of the Dotcom Bust.

(Although this time around, the tariff mess seems to be popping the bubble earlier, and maybe a little less violently, than 25 years ago.)

Regardless, I expect the job market this year to be brutal for software engineers. We have a lot more programmers than jobs for the time being, after years of heavy hiring around the pandemic, so it's worth thinking about how to get through it.

The first question, hard but important, is: how serious are you about this? In 2002, part of how things resolved is that a lot of folks dropped out of programming and found something else to do. By that point, we had tons of folks for whom it was just a job, rather than a passion, and many of them found greener pastures elsewhere. That's 100% sensible, and I expect a fair amount of it this year.

For those of us who do consider ourselves to be software "lifers" -- the ones who can't imagine not programming on a constant basis -- I have two key pieces of advice:

  • Never Stop Learning
  • Never Stop Coding

On the first point, self-driven learning is the heart of software engineering: as a rule of thumb, I believe in spending several hours every week, even when fully employed, learning new stuff -- staying on top of things is a key part of my job in an industry that is constantly evolving.

That becomes more true when you're unemployed: you should take the opportunity to learn new languages, new techniques, new technologies. Take the time to expand your toolbelt and figure out new things you can do and find fun.

On the second, take the downtime as a chance to buff your portfolio. For most of us, our dayjob work is pretty hidden: the code is proprietary to our former employers, so we can't show it off.

So don't take too much time as enforced vacation. Instead, once you have your head straight, get back to "working" a full day every day on something open source. That both shows that you have some initiative, and lets you show off your chops to prospective employers.

Indeed, this is exactly what worked for me in 2002. I taught myself the then-newish C# language and built a dumb little shareware application in it. That proved directly relevant to my job hunt: I wound up getting hired to build the .NET middleware backend for a startup that I had my eye on.

(This time around, I'm taking the time to bring Querki, my own little product, up to modern snuff after years of neglect -- that's teaching me a lot about AWS, and should give me a chance to turn that crufty ancient Scala code into something I'm more willing to show off.)

Mind, it's still hard -- you have to put a lot of mental effort into not letting it get you down. But having a project to focus on will help with your mental game, and can help with the job hunt in unexpected ways. I recommend it.

jducoeur: (Default)

My technical blog is very Scala-centric, so not too many of the folks here are interested in it.

But for the programmers in the audience: I just finished posting a long-simmering series of articles about testing Scala services that some of you may find fun. It's somewhat heretical, including premises like:

  • Unit tests are mostly a waste of time for idiomatic Scala services.
  • You should focus on "scenario tests", that hammer the APIs and stub all externalities.
  • 100% test coverage is the only meaningful number, and you should get there.
  • Your code should be designed specifically to be testable, including hooks as needed to expose internal events to the test harness.

Not all of it applies to other languages and situations, but a fair amount of it does. So if you are curious about the topic, give it a read -- I'd love to get some conversation going about the topic, either there or here.

jducoeur: (Default)

Spreading the word for the other software-law geeks: the decision has come down on Oracle v Google, and it went the right way.

Summarizing very briefly (and possibly a little inaccurately -- IANAL, and I haven't read the ruling in detail yet): the Android phone operating system, like a large fraction of the software world, is more or less built on top of the Java Virtual Machine, which was invented by Sun decades ago and bought by Oracle. Google decided to reimplement the API for the JVM to suit their needs -- basically, providing a new implementation for the existing interface. This is totally normal (there are lots of reimplementations of parts of the JVM), but Oracle asserted that the API is their intellectual property, and sued.

(Note that pretty much everyone agrees that the implementation -- the code itself -- is copyrightable. The question was about the interface -- essentially, how you call that implementation from other code. If the interface is protected by copyright law, it becomes a legal minefield to try to write compatible, alternate implementations.)

Suffice it to say, the lower courts went with Oracle, and much of the industry has been on tenterhooks ever since. A lot was riding on this -- if Oracle had won, it would have tossed an enormous spanner into the software industry, and probably done a lot of damage to smaller companies. (Among other things, Querki's user interface is based on Scala.js, which necessarily reimplements a fair chunk of the JVM API. It's unclear whether Scala.js would have been able to survive if Oracle had won; in turn, that could have destroyed my company.)

The implication here, I believe, is that reimplementing APIs is now officially considered fair use, so the law matches the way the software industry has generally assumed things should work. So while on the one hand, this seems like an obscure technical point that most people don't care about, for those of us in the field it is extremely important, and really good news.

So yay for the Supreme Court for getting this one right...

jducoeur: (Default)

Howdy, all -- looking for thoughts, especially from the engineers in the crowd but not necessarily limited to them.

I've just found myself as one of the leaders of a big new software project -- big enough that we're going to be needing to spread the work across several teams, in various places around the world. That includes India, so figure ~12 timezones away from me. Collaboration is going to be a serious challenge, and one that we need to take seriously if we're going to succeed.

I'm sure that some of my friends have dealt with similar problems, so I'm looking for any and all thoughts. Tools, techniques, beartraps that you've run into -- this is an open-ended conversation, just keep it civil and accept that the team is what it is. I probably don't have the power to force this to all be on-shored, so the question is, how do we make the best of it?

We can probably slice-and-dice it so that different teams are working in different repos with distinct areas of responsibility, at least. The real question is how to manage questions and conversations about everything from coding style to architecture to requirements when we can't easily all get into a meeting together. It's not a rare problem, and I suspect there are best practices I don't know about yet.

Thoughts? Ideas?

jducoeur: (Default)

Well, that's kind of neat. Rally Health (my dayjob) just relaunched its company Engineering Blog, with a new article by me.

It's strictly for the programmers, showing how to build a Redis serializer/deserializer using typeclasses in Scala. If you're interested in how programming works in a more modern way, I recommend checking it out -- it's a good illustration of how this technique (which came from Haskell, but is now central to Scala and spreading to other languages) works. Questions more than welcomed here: I enjoy teaching this stuff...

jducoeur: (Default)

This one is mainly aimed at programmers, but I'm trying to teach a bit of programming, so it's not just for the FP geeks. (This is basically a bit of Functional Programming 101.)

In a comment on my earlier post, [personal profile] cellio asks what a Monad is. It's one of the most fraught questions in modern programming, but let's give it a stab. Bear with me -- this takes some explaining, and I am trying to avoid The Curse of Lady Monadgreen. This will be a practical description, rather than a precise formal one.

First, Functors

Let's consider several data types that we find in Scala. (And many other languages as well, often under other names, but I'm going to use Scala for my examples since it's what I know best. The concepts here are very general, but some languages express them better than others.)

On the one hand, take val o: Option[T]. This means that o is a box that may or may not hold a value of type T: o is either Some(t) or None. It's kind of like the idea of being able to be null, but much more principled. (Many languages use this either instead of null or provide it as an alternative.)

Next, let's look at val l: List[T]. This means that l is a box containing as many Ts as you want (possibly zero) with a specific order. (As opposed to Set[T], which has no intrinsic order.)

Finally, let's take val f: Future[T]. This one doesn't exist in as many languages: it basically says that f is a box that will eventually contain a T, assuming all goes well. (If all does not go well, it will eventually contain an error.) It's a good way to deal with asynchrony in programs, and can replace locks and callbacks and other such hell in many cases.

These types are all Functors. This means that they have a method called map(), which means "do the following transformation with every element in me". So for example:

  • o.map(x => x * 2) -- if o is, say, Some(5), this will return Some(10). OTOH, if o is None, the result will still be None.
  • l.map(x => x * 2) -- if l is List(1, 2, 3), this will return List(2, 4, 6).
  • f.map(x => x * 2) -- this returns another Future; if f eventually contains a 6, the resulting Future will eventually contain 12. And if f eventually returns an error, this resulting Future will contain that same error.

So the concept of a Functor[T] is that it is a box that contains "T-ness" in some fashion. You can transform the T's inside of it, getting another of the same kind of Functor with the transformed values.

Functors to Monads

All Monads are Functors, but with an additional kick: there is a sensible way to nest them. All of the above types are also Monads, and their Monad-ness can be expressed in for comprehensions, like the following.

val maybeUser: Option[User] = ...
val maybePhone: Option[PhoneNumber] = for {
  user <- maybeUser              // Option[User]
  profile <- user.maybeProfile   // Option[Profile]
  phone <- profile.maybePhone    // Option[PhoneNumber]
}
  yield phone

(I generally find it helpful to pronounce the <- arrow as from "in". So the first line of that for comprehension reads roughly "for each user in maybeUser".)

What the above is saying is:

  • I may have a User.
  • If so, put that User in a value named user.
  • If that user has a value in maybeProfile, put that in profile.
  • If that profile has a value in maybePhone, put that in phone.
  • If all that worked, return the phone number.

We are able to nest values or functions of type Option, and get another Option out at the end. If any of those steps returned None, then we get None out the end.

Next, let's do the same with List:

val regions: List[Region] = ...
val allCustomers: List[Customer] = for {
  region <- regions              // List[Region]
  dealer <- region.dealers       // List[Dealer]
  customer <- dealer.customers   // List[Customer]
}
  yield customer

This is saying:

  • Start with a List of Region.
  • For each of those Regions, get all the Dealers.
  • For each of those Dealers, get all the Customers.
  • Return all of those Customers.

It's the same concept: there is a logical concept of nesting. More importantly, there is a specific way in which you nest: in the case of nesting Lists like this, the results will all be concatenated together: the Customers for each Dealer in order in the resulting List, and all of the ones from Dealers in the same Region together.

Finally, let's try Future:

val userId: String = ...
val profileFut: Future[Profile] = for {
  user <- userDb.loginUser(userId)              // Future[User]
  prefs <- preferenceService.getPrefsFor(user)  // Future[Prefs]
  avatar <- photoService.getAvatarFor(user)     // Future[Photo]
}
  yield new Profile(user, prefs, avatar)

Each step in this case is a function that returns a Future. Putting it together:

  • First, try logging in with the given userId, and get back a box that should eventually contain a User.
  • Once we have that User, get a box that will eventually contain their Prefs.
  • After we have fetched the Prefs, get a box that will eventually contain the user's Photo.
  • When we've obtained all of that, assemble a Profile out of it.

Again, we are nesting these operations, and again, Future imposes some details: these steps will be conducted in order, each one starting after the previous one has finished, and if any step returns an error, everything after that will fall through and return that error instead of trying to continue.

Note that each kind of Monad knows how to combine with itself. That doesn't mean that they can easily combine with each other -- there are sometimes ways to combine different Monads in sensible ways, but it's a bit ad-hoc: not all combinations make sense.

Conclusion

So those are the high concepts. A Functor is a sort of box that contains "T-ness", where you can transform the Ts inside of it. A Monad is a Functor that has specific rules for how it can be nested within itself.

And yes, the names are weird. They come from Category Theory, a branch of abstract mathematics that turns out to be really useful for serious programming. The video linked from my previous post includes the legendary line, "a monad is a monoid in the category of endofunctors": literally true and correct in Category Theory terms while being utterly useless for actually understanding anything.

Anyone who wants to dig into this a little should pick up the delightful book How to Bake Pi, a fairly slim, Kindle-friendly book that teaches Category Theory in terms of baking: each chapter starts with a recipe, and then shows how that recipe relates to a mathematical concept. It doesn't teach programming per se (and requires no background in either math or programming), but it provides the underpinnings that this stuff all grew out of. I found it invaluable for getting comfortable with this stuff.

For the actual programming concepts, including Functors, Monads and other such fun types, I currently recommend the documentation for the Cats library -- the Cats community has taken documentation really seriously, and the documentation of each type does a delightful job of exploring why that type works the way it does. It is aimed at programmers, though -- I wouldn't recommend coming into it completely cold.

Hopefully folks will find this at least a little helpful. Questions welcomed...

jducoeur: (Default)

Content warning: Nazis, and mockery of both OO and FP.

This one is only for the hardcore programming nerds out there -- I suspect everyone else will just scratch their heads at it. But I thought it was horribly funny:

Video on YouTube

jducoeur: (Default)

I don't normally post simple links here these days (that's what Facebook/MeWe are for), but this one tickled my fancy, and besides -- it's about programming. And Mixology.

It's an article about Cocktail Similarity: using similar algorithms to the ones we use to ask "how similar are these two Strings?", applied to cocktails instead. It includes a dynamic generator for how to change any given cocktail recipe into any other cocktail recipe, charts of similarity, and lots of code.

It's wonderfully nerdy in a rather XKCD kind of way: taking two nerddoms and smashing them together. And it's Negroni-centric, which I totally approve of. Check it out...

jducoeur: (Default)

No, I haven't been posting much here lately. That's mostly because life has reached a pretty good pinnacle of crazy-busy.

Obviously, Querki continues to dominate my thoughts a lot. The project that we were going to do for Arisia didn't happen this year (since Arisia got Complicated), but has rather suddenly turned much more serious for next year, with a lot more people on board and the system likely because fairly central to Team Arisia.

I just got a new client at my dayjob. (Actually the same client I had for most of last year, but a different group -- last week involved a bit of amusing chaos as they shipped me an underpowered laptop, I pointed out that I needed something beefier, and then they figured out that my old laptop hadn't been wiped yet, and would I like it back?) So I'm in heavy ramp-up there.

After about 18 months of officially being the deputy of the Boston Scala Meetup, the founder finally recognized that he was a bit burned out, and he formally handed that off to me. So I ran a small survey of the community there, created a new Slack group as a result (and am now trying to get people to actually use it), and am starting to work out this year's Meetup schedule.

And today's new fun? I've had a talk accepted at a conference for the first time!

For all that I've been teaching Stuff (SCA dance most notably) for decades, and have been teaching Scala and presenting at Unconferences for several years now, I've never really done the conference circuit before about four years ago, and I've never done a talk before.

In this case, it's the Typelevel Summit, so I've dived into the deep end here. NE Scala is my "home" conference, a joint production of the Boston, New York and Philadelphia Scala Meetups -- this year is in Philly. But it's really three conferences joined at the hip: the Typelevel Summit, NE Scala proper, and the Unconference. The Summit is in some ways the bigtime: a gathering of the Scala-functional-programming hardcore, members of a growing group that encourages and collaborates on FP-centric Scala libraries. It includes a lot of the heavy hitters of the Scala world.

So I'm a tad intimidated, but also rather excited. My talk is specifically intro-level, and is about my own journey to finally building a pure-FP system for the first time -- in this case, Querki's new API-level test harness. The resulting code is some of the prettiest I've ever written, so I'm going to burble a bit about how that code evolved, and show off the relevant FP concepts that make it possible.

All of which goes to explain why I haven't had a lot to say about SCA, Fandom and stuff like this -- right at the moment, programming is dominating my brain, so I've mostly been posting over in my professional blog, which has wound up very Scala 3-centric for now. But I'll try to find some time to at least diarize and do some reviews here...

jducoeur: (Default)

I was just reminded that I've never shared publicly the document of Useful Scala Resources that I put together for Scalabridge a few months ago. Here it is, if anybody is interested.

Note that this is just an outline, but it's an outline with a considerable amount packed into a few pages. If anybody's interested in more info, I'm always happy to chat about this stuff...

jducoeur: (Default)

Fascinating article here about Priority Guides, a UX design tool that they are presenting as an alternative to wireframes. The core notion is to focus on the content of a page, using a discipline that specifically discourages you from worrying about the visual layout in this stage.

Very neat food for thought, especially for Querki. It would probably be easy enough to build a lightweight Priority Guide Designer in Querki, to use for future design of the system, and I suspect it would help prod things in more usable directions. Indeed, if it works I might make it into an app/mixin for others to use...

GraalVM

Apr. 17th, 2018 02:26 pm
jducoeur: (Default)

(Mainly for the programmers.)

Today in tech news is Oracle's announcement of GraalVM -- yes, that's "graal" as in "holy grail", and I'm sure they intend it. They claim that this new VM will:

  • Run in diverse environments.
  • Start fast and run fast, thanks to optional precompilation and linking.
  • Cover all major programming languages.

How they heck they are accomplishing that last one, given the diverse environmental expectations of different languages, I have no idea. One of the lessons of the Scala.js and Scala Native projects is that, yes, interoperability in diverse environments is possible, but it ain't simple. So I'm immensely curious what the interoperability in the GraalVM environment looks like.

It seems to be more than smoke and mirrors, though: they claim to already support all of the JVM languages and JavaScript, and they're working on Ruby, R and Python -- a nicely diverse set of target languages. And Twitter is apparently already using it in production. So this looks quite real, and if their performance claims stand up, it may be quite important.

Of course, this is coming from Oracle, who are not historically a fuzzy and cuddly company. Especially in light of their recent court win in the long-and-tiresome-but-important API battle against Google, I am quite concerned about the IP provisions are around GraalVM -- in particular, what patents it involves and what sort of copyrights they are asserting. Depending on the details, it may or may not be wise to build on; I think it's likely that this is Oracle's stake in the "technology lock-in" game.

That said, it's damned intriguing, and I'm curious to see how it plays out. In the meantime, I need to find some time to read into it...

jducoeur: (Default)

I've mentioned before that I now have a dayjob -- Artima, which is a small, Scala-focused consultancy. We currently have about half a dozen engineers, and are wrestling with the problem that no two of us live in the same timezone, much less state. (A couple aren't even on the same continent.)

We're trying to figure out how best to deal with communication among such an asynchronous team, where even video meetings don't work well due to timing. In particular, informal communication -- while we're okay having conversations in GitHub Issues where that is appropriate, we don't have a good place for transient, topical discussions. (We're also using Slack, but that's kind of so-so for asynchronous communication.)

This can't be a rare problem nowadays -- distributed teams are increasingly common. So here's a question for my friends and acquaintances: any suggestions of tools? What have you found to be helpful for distributed teams, especially for teams spanning many timezones?

jducoeur: (Default)

Just a quick shout-out to the Scala Center -- the group that shepherds the Scala language -- for their new accessibility initiative. They're exploring how to get the compiler working in a usable way with screenreaders, so that sight-impaired folks can actually make use of it.

(See the linked article and the SCP behind it for a bit more info, but the heart of the point is that literally rendering Scala code to speech produces nigh-incomprehensible results. So they're starting to study how to express the concepts in a way that can be understood through speech.)

jducoeur: (Default)

Got home last night from California, where I spent Thursday and Friday teaching a new course on Concurrent Scala. (We'll eventually get that listed on the company website.)

It's been an interesting experience. While I've done a fair amount of Scala teaching (both in conferences/Meetups and officially through Artima), and of course I've been teaching dance and stuff forever, this is the first time I've taught a whole programming course that I wrote largely on my own.

In general, I think it went pretty well. Some students thought parts were too elementary, while others thanked me for covering the basics, so I think we got the level-set about right. I didn't see too many people yawning, even through the epic three-hour talk on Friday morning, so I seem to still be pretty good at holding folks' attention and explaining stuff. It was a good class: larger than I'd expected, with a good deal of give and take with the students. As with dance, a lively group makes teaching a lot more fun.

The only serious fail came during the second day's Project Time. For this advanced class, instead of our usual approach of alternating short talks with half-hour blocks of formal exercises (with unit tests to check whether your answers are right), I instead did much more in-depth talks, and then had the students pair-program on less-formal projects. Basically, I gave them an initial skeleton app, and a stack of stories, which they were then to go off and implement. At the end of the day, we got volunteers to come up and show what they had written, and had the whole class talk about it.

All of which went fine until most of the way through Friday. Since it was a dead run getting the class finished, I hadn't gotten around to actually working through the projects myself -- after all, I knew the topics deeply, so I was confident it was all doable. Only I'd trusted the documentation while I was writing the skeleton app -- and as we all know, documentation lies. So the skeleton was actually misconfigured for what I had assigned them to do, and we lost half an hour during the projects figuring out the correct config settings.

But all in all, as fails go, I'll take it -- for the first run of a course, that wasn't too embarrassing, and I'm going to go fix it this week, so it's ready for next time.

And with that survived, I now get to do stuff that's a little less insane for the next couple of weeks...

jducoeur: (Default)

Just a quick link today, particularly useful for programmers who are trying to grok Functional Programming. This article describes the heart of the difference between imperative and functional programming in terms of a tiramisu recipe. (And a bit of Python code, but you really don't need to know Python to get the idea.) Well worth a read...

jducoeur: (Default)
Yesterday, I officially admitted to myself that I have been fighting a cold, probably for the past week and a half. It's been really slight -- just some sinus crap and a constant, moderate, dry cough -- so I haven't felt "sick" per se. But it does get draining after a while.

At this point, the biggest problem is that I'm just plain *tired*, and have the attention span of a particularly dim hamster. This isn't exactly good for my productivity, either for work (either for Artima or Querki) or fun projects.

But in the meantime, for the programmers in the audience (especially anybody into Scala), have a crazy little brainstorm from this morning...
jducoeur: (Default)
For those who are interested in it: I'm experimenting with posting some of my technically-focused articles on Medium. The first one is up: Don't hand out masks of your own face.

Don't worry, I'm not abandoning Dreamwidth -- most stuff will remain here. But I'm going to play with using Medium as a professional/technical blog, for articles where I am spouting off on techie subjects, and don't care quite as much about promoting followup conversation (which works better here).

So if you're interested in the programmer-y stuff, I encourage you to follow me on Medium, and we'll see where that goes...

Profile

jducoeur: (Default)
jducoeur

May 2026

S M T W T F S
     12
3456789
10111213141516
17181920212223
242526272829 30
31      

Syndicate

RSS Atom

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags