Libyear

Crier1002 | 228 points

As a person who works on automated dependency updates (depshub.com), the libyear indicator is often not very useful. There are several other indicators to consider, such as release frequency, update type (major/minor/patch), the dependency's criticality for your project, etc.

Instead of solely focusing on reducing the libyear for your projects, a better approach is to minimize the steps needed to keep your project reasonably up to date. For instance, think about managing 20 PRs weekly to update various package.json packages versus 1 PR for critical dependencies when necessary.

It's important to note that updating dependencies is not a consistent task that can be done at the same pace all the time. Expect varying update volumes and complexities that may need attention at different times. Setting a fixed configuration for, let's say, 10 updates per week may not be effective, as it could lead to dealing with unnecessary updates regularly (e.g., aws-cli, which has almost daily releases).

Finding the right balance between keeping your project up to date and spending too much time on dealing with dependencies is the hardest part here that doesn't have a 100% right answer yet.

semanser | 11 days ago

Isn't "we are 5 major releases behind" more obvious that "two libyears".

> If your system has a one year old dependency and a three year old dependency, then your whole system is four libyears old.

How far down the tree do we go? Either fully, which means that one project with 365 one day old dependencies is 1 libyear old. Or not at all, as the rails example suggests, in which case if I have a wrapper around rails that I bump to an old rails version, anyone using my wrapper would have older rails but a fewer libyears?

There is no single answer to all of this, because it's too complex to boil down to a single number. But I think it's a bit odd to introduce a whole new thing that doesn't measure at all what's changed.

IanCal | 11 days ago

Can't see this as being particularly useful. Libraries under active development will have larger more frequent releases (but small number of libyears out of date) whereas mature software with only occasional bug fixes may be 10s of libyears out of date.

barbegal | 11 days ago

The linked website does not explain what a libyear is. It gives two examples:

> Rails 5.0.0 (June 2016) is 1 libyear behind 5.1.2 (June 2017).

and

> If your system has a one year old dependency and a three year old dependency, then your whole system is four libyears old.

which don't explain much.

I suspect what they meant to say is that Rails 5.0.0 (June 2016) is 1 year (not libyear) behind 5.1.2 (June 2017) and that the "libyear age" of a project is the sum of how old each of its dependencies is. But if so, they should say so clearly somewhere on their page.

umanwizard | 11 days ago

Just remember that blindly updating dependencies that no one trustworthy has reviewed is opening yourself up to supply chain attacks.

Blindly upgrading is worse than never upgrading unless you are addressing a specific CVE that impacts you.

Public open source code is code you did not have to write which can be a time saver, but you do not get to skip code review.

If you do not have time to review 2000 dependencies, then you should drop them favoring simple functions that only do what you need.

lrvick | 11 days ago

libyear assumes that constant development happens all the time in a library and software has to change and grow constantly. There are some libraries that are just mature and doesn't need to change. 5.0.1 could be released 5 years ago, and 5.0.1 today with just changes to docs. It doesn't mean that it took 5 libyears to develop and release the new version. This is the type of thinking that attackers used in xz trying to pressure original author to add more official maintainers, because he wasn't merging and updating code fast enough. "You're not merging and releasing our code fast enough, therefore you're doing bad job".

What would be other measures that could be similarly useful? Lines of code or story points? Maybe even a number of tests added?

agilob | 11 days ago

I went through this project before.

For some applications it might be of great use but for a vast and complex applications architecture, the libyear metric might only oversimplify the complexity of dependency management,compatibility issues, updates and security patches, etc

I noticed that it focuses only on the age of dependencies without considering other factors like the how critical is the update, and how stable it is, and the improvements in newer versions, etc.

avi_vallarapu | 11 days ago

What's nice about the "libyear" concept is that it exposes the cost of indiscriminately pulling in 3rd party libraries.

For example, I recently went through a project to bring 3rd party dependencies up-to-date. I noticed that we were using a very old mathematics and statistics library.

On closer inspection, we were only using one function from the library to calculate the mode of a list of numbers. Looking at the library's source code, it was about 50 lines.

Now, a decent programmer can recreate such a function in 1-3 hours, including a unit test. This is what we did instead of including the dependency.

A naive programmer might think that sucking in the 3rd party library "saves" 1-3 hours, but that's not the case: Every few years someone will audit the libraries we're using as part of a security audit, or a legal audit to make sure that we're in compliance with open-source libraries. The stats library will incur a 1-2 hour cost in each audit.

Furthermore, every 1-4 years we'll need to update the library, because changes in the programming language, runtime, OS, ect, mean we'll need at minimum a recompile or similar tweak to take advantage of some new language feature or constraint. The 3rd party dependency could add 1-4 hours to such a project.

Thus, because libyear shows an increasing cost associated with the library, it's easier to explain why it's better to spend 1-3 hours writing a simple function (and unit test) than to bring in a 3rd party library to do the same thing.

gwbas1c | 11 days ago

One step away from rediscovering voltime.

Time flows faster in periods of high volatility and slower in periods of low volatility. Instead of measuring time directly it should be adjusted by things like changes committed, LOC added/removed, CVEs opened/closed, etc.

baq | 11 days ago

Matters a lot what kind of applications the library is for. Being a couple of years behind in mobile application development usually means you have to spend a week piecing together a development environment to get the crap to build so you can start the library upgrading process.

A couple of years hither or dither with grey-haired Java libraries matters very little. There might be some vulnerabilities but you probably know about them and have workarounds, and sometime next year it's likely you'll be allowed a month or two to do 'life cycle management' in the dependency stack.

cess11 | 11 days ago

It's nice to have a name for this, and for it to be quantifiable. I could see this on some kind of product dashboard - maybe automatically generated.

But, while I appreciate the need for simplicity, I also wonder if it would be wise to scale dependencies by how prevalent they are in the codebase. For example, if I'm using a five year old version of react but the library I use to convert temperature units is up-to-date, then thats bad. But if I'm using the latest react and the conversion lib is old then thats less bad.

Probably feature creep though...

andyjohnson0 | 11 days ago

They've succeeded in creating a single metric that's easy to calculate, but IMHO, it fails to be very useful for common use cases.

Basically, it just uses the difference between the date the library version you are using was released and the current date if there's a newer release available.

Eg, if you are using a library that has been unchanged at 1.0.0 for the last 10 years, you'll be 0 libyears behind that whole time. Then one day, the developers of that library release 1.0.1. One minute after that hits the package repositories, you are immediately 10 libyears behind.

This makes it pretty useless as a metric for tracking how outdated an application really is. Eg, as an ops/SRE/security person, I'd want to be able to run this on a product team's code and have a single number that tells me whether they're reasonably up to date or seem to be ignoring their dependencies and letting technical debt pile up. A team could've been on the ball, keeping every dependency updated daily for years, but if I use libyear to evaluate them right after that that 10 year old dependency updates, it's going to look like they've been negligent.

I have an open issue on the Python implementation (which ironically(?) hasn't had any commits in three years) asking for clarification: https://github.com/nasirhjafri/libyear/issues/35

thraxil | 11 days ago

This is a hugely misleading indicator to rely on. Not only it sums up all the time behind in dependencies which is more than confusing to start with but it also leaves the end user puzzle what to do with this information.

Let's assume my software project is 120 "libyears" behind. What's next? What risks am I exposed to? What should I do?

Think of a notorious python2 vs. python3. I am in 2019 and my software project has it as a dependency. My team has assessed that migration to v.3 will require another year of dealing with all the breaking changes. And while brainstorming we are thinking from the risk and cost-benefit perspective. Time per se is relevant only in the context of effort required to perform the migration.

From the supply chain security standpoint I could not care less about time as well. If I am using library X of version 1.2.3 and it ticks all the boxes, has no performance impact, has 0 problems, 0 vulnerabilities (including the results from public, third party and internal code audits) I will continue using it even if version 2 is out, especially if it requires reassessment of risks and some code refactoring due to breaking API changes.

If I want to automate my dependency management I will rely on tools that will tell me about my risks or potential missed benefits from the newer versions. Time will be taken into account only in terms of time needed for mitigating the risks directly impacting my piece of software.

nrvn | 11 days ago

It's worth also reading https://chaoss.community/kb/metric-libyears/ - as noted elsewhere, regularly updating libraries, or a library that infrequently pushes out large breaking changes will not reflect as easily in Libyear, but it's worth having it as something to gauge out-of-date-ness

I've been using that alongside some other metrics for providing insights into how behind teams are on updates

jamietanna | 11 days ago

The explanation could be better, but I really like the idea.

It punishes you for not updating your dependencies and for having too many direct dependencies. But it doesn't punish you for indirect dependencies (that you have little control of), or libraries that are "done" (since it compares to the newest stable release, not the current year). A sensible balance.

Maybe one could write a browser extension to display the libyear of GitHub pages?

BoppreH | 11 days ago

Can we also have libloc (metric based on #lines of code)?

amelius | 11 days ago

Don't make me wave the Diffusion of Innovations chart at you all:

https://en.wikipedia.org/wiki/Diffusion_of_innovations

libyear is an opinionated metric that prioritises less well tested software. Meanwhile, companies pay a lot of money for RHEL and other products that promise a stable environment that freezes specific (major) releases of software for years - and also promises backports of any necessary security fixes, without those pesky new features and breaking changes that come with using bleeding-edge releases.

Different people, projects, organisations, all have different risk appetites. We need all of them working together; late adopters wouldn't have the stability they crave if early adopters didn't exist to test the crazy broken fresh software.

While everyone needs to manage dependencies, there's no one right way to do it, so everyone does it their own way. They only thing we can probably agree on is doing _no_ maintenance on dependencies is a bad thing.

amiga386 | 11 days ago

This is a fantastic way to encourage churn and ensure developer job longevity.

noobermin | 11 days ago

A great metric for job security, not necessarily for better software: Unless it concerns security or correctness, I prefer an old but audited version of a library anytime over a newer version that I have to audit again.

A metric like this will be loved by PMs and loathed by developers who have to leave a known, sane state, update and deal with the fallout later on.

jlg23 | 11 days ago

While granting that libyear is clear in what is measures, I still think it measures the wrong thing. What should we be measuring?

I have some ideas for my projects, but I don't have the answer for your project.

Semantic versioning ain't the only game in town for sure, and I'm not anchoring on it as the best or only way.

But I will say this: when one has figured out what is important to measure, build metrics for that. You almost certainly will need to factor in supply chain security. And probably some metrics for recency about the hardware platforms you deploy to. This could look like a weighted score, perhaps. But it is unreasonable to hope that libyear or semver to do that for you.

xpe | 11 days ago

This assumes that code that just works incredibly well and hasn’t needed an update in years is inferior to frothy untested code or broken code constantly requiring bug fix PRs.

api | 11 days ago

I agree with other comments that it's not a perfect measure but it's a solid step in the right direction from having no metrics at all.

The libs we're measuring up to could have their own libyears to upgrade, but we can only control what's in our hands.

Sometimes a small security patch is worth more than a major version bump of features, so I consider measuring the time instead of major versions a benefit.

tomaszsobota | 11 days ago

I’ve been wanting to make a similar indicator for the work I do at endoflife.date. IMO, a realistic upgradability metric would be linked to the “hardness of the upgrade to a supported version”, which is much harder to answer and quite contextual in how you are running each dependency.

But libyear is a good metric to have as prior art in the field.

captn3m0 | 11 days ago

If you're using libraries from 10 years ago, maybe it's because you used good tools.

derrida | 11 days ago

I propose a different metric, version points: subtract version number of the currently used library from the version number of the latest version. Translate to semver first if possible. Also, a release addressing a CVE adds extra ten million points.

thih9 | 11 days ago

Related discussion:

Libyear – a simple measure of software dependency freshness - https://news.ycombinator.com/item?id=24975339 - Nov 2020 (16 comments)

imadj | 11 days ago

This is such a good idea. Another one I would like to have is a single number repressing legacy code. I'm not sure exactly what but is there a way to represent the code which people are writing workarounds for.

newswasboring | 11 days ago

As a worthless junior dev, thank you for the post. I am seeing a general sentiment of reluctancy towards an introduction of yet another dubious metric in an environment where "software quality" is hijacked to mean something else.

This lead me questioning how good is it to judge a project by its age + last commit (+ project size/complexity + funding/community), as this is what I do in practice. I agree that SemVer isn't really designed to be human-readable and is a rather meaningless / deceiving metric due to divergent practices of different developers.

impulsivepuppet | 11 days ago

Very rarely do I so vehemently disagree with a particular argument in software. This idea epitomizes much of what is wrong in the industry.

We can all agree security updates are essential, but a lot of libraries are “done” from a functional perspective for a majority of their existing use cases.

Yes updates can be needed because interfaces break between other programs, standards evolve in backward incompatible ways, performance improvements can be made, etc. But much of the updates I see are changes for the sake of changes.

You could use a 5 year old version of React for example, and modulo some set of security fixes if any, you could have a robust application.

Sometimes software is just done. We are better off for accepting that idea. Get us off the update hamster wheel and stop the enshittification.

sudo_bang_bang | 11 days ago

I just added libyear support to ocicl for Common Lisp.

atgreen | 9 days ago

The metric should be called libtime, and measured in pcyear.

bmacho | 11 days ago

So, how many libyears were that xz dependency out of date?

Libyears are meaningless. A library either has known vulnerabilities or it doesn't. When it doesn't, old is often better than new one.

thriftwy | 11 days ago

Super idea :)

betimsl | 11 days ago

[dead]

pomoke | 11 days ago
[deleted]
| 11 days ago

[flagged]

gamegod | 11 days ago

nice metric!

nikolayasdf123 | 11 days ago