Why you shouldn’t use inline styling in production React apps
Why you should use refs sparingly in production
Videos
Learn REACT JS in just 5 MINUTES (2020)
JavaScript for React Developers | Mosh
Why you shouldn’t use inline styling in production React apps
Why you should use refs sparingly in production
JavaScript for React Developers | Mosh
Why use redux, reasons with clear examples
Logrocket it helps you find bugs in your redux apps
What Is Redux: A Designer’s Guide
Do you need redux with react hooks?
Videos
What is Redux?
This page is dedicated to Arduino Alternative MicroControllers. These are similar to Arduino but more powerful or add some special feature.
Wemos D1 Mini + 0.96 Inch SSD1306 OLED Display Using SPI – cool article
What is worth salvaging from an old smartphone?
How to Measure Temperature Very Accurately With an Arduino and a TSYS01 Temperature Sensor Board.
The purpose of this page is to list links to resources about interesting arduino projects. Many are videos. I list them here so I can find them again later for review more easily.
Interface BME280 Temperature, Humidity & Pressure Sensor with Arduino
This link is to a little research on Humidity sensors, the most common ones anyway.
https://jlcpcb.com This awesome website has a cool tool for designing PCB’s for free. They also have great prices on printing the PCB after you design it. Super affordable prices.
Awesome tiny Spectrometer. WOW
This very short video gives a quick overview of the concepts in an easy to follow way.
EEVblog #437 – Removing SMD Parts with ChipQuik
Making The Move From Scala To Go, And Why We’re Not Going Back -> a great article about some reasons why a company switched to golang. It mentions some important things to consider. Golang is great for microservices.
Golang book. Free online book.
50 Shades of Go: Traps, Gotchas, and Common Mistakes for New Golang Devs
Golang Modules explained
More about Golang Modules
Golang Slices explained
Golang pointers explained in the tour
Golang interfaces explained. This is a very helpful article. I found the interfaces section on tour of go to be nonsensical jibberish. Here is the pure jibberish
var a Abser
f := MyFloat(-math.Sqrt2)
v := Vertex{3, 4}
a = f // a MyFloat implements Abser
a = &v // a *Vertex implements Abser
How is this implementing anything? It looks to me like assignment? Makes ZERO sense. Most of the tour is awesome and makes sense but this entire section is pure fail. It causes more questions than answers. Like this
// In the following line, v is a Vertex (not *Vertex)
// and does NOT implement Abser.
a = v
Ok I am new. This to me looks like reassignment. Once again how does assignment make something implement something? And why not explain it to the new users? Any details as to what is going on would be helpful to new comers. If you quote it out and run the program it works. This section needs heavy updating and explaining. This is purely WTFF??? This is literally the absolute worst part of the entire Tour. This is where I hit my WTF moments and had to start using google to DECIPHER the encoded message.
Thinking in Go. This article is a must read for anyone coming from an OOP background such as Java wanting to understand Golang. There are no classes. No inheritance. No generics. No this. No that and No. Golang requires thinking entirely differently. Interfaces are the hardest thing to wrap my mind around so far. The implicit magic is something I don’t like I prefer words like implements to make my code more clear. If I could just find good enough information I’d understand it. I literally have to undo all of the years of OOP damage. When I first encountered Golang I heard that interfaces confused most new people, I understand why now. It is not just interfaces it is learning to think and build software in an entirely new alien way.
More on Golang Interfaces — because they are nothing like interfaces you have face in other languages. The whole implementing thing is just totally wild. I hate implicit bullshit. It’s just unneeded magic for no reason other than to drop a few characters.https://www.digitalocean.com/community/tutorials/how-to-deploy-a-go-web-application-using-nginx-on-ubuntu-18-04
Thinking about Interfaces in Go — another great article about Golang interfaces. Interfaces are the most complex thing in go, so multiple references helps more.
Go for Java Programmers — this is an awesome series of articles for java programmers coming to Golang. This is also helpful to PHP programmers since PHP is so similar to Java these days.
Go in VSCode: Must-have extensions and some limitations
Building Web Applications with GO — a free online book about how to build a web app with golang
How to deploy a Golang Application on Linux with NGINXÂ
 Go: the Good, the Bad and the Ugly  An article with lots of good information about Gotchas in Golang and some best practices.
Golang: Concurrency is Hard; So What Can We Do About It? A very good article about concurrency in Golang
Everything you need to know about Packages in Go – a great article all about packages.
Publishing Golang packages – golang article about how to version packages/modules
Why you should use a Go module proxy– why and how to create a go module proxy
Go 1.13 for Private Repositories – What are private repositories
7 common mistakes in Go and when to avoid them by Steve Francia (Docker)
I am not done with this excellent book yet, but I decided to go ahead and publish this in case it may help anyone else. If you are trying to decide on a book to buy about Microservices, this is the book I suggest after much research. You will open this book many times when designing your systems, it is that full of good information.
Microservices Patterns is an Excellent book by Chris Richardson. This book contains so much useful information, mine has started to look like a coloring book with all of the underlining notes and highlighting. These are my notes for myself so I can re-find useful information later. Since I have several books on the subject and pages of links, it helps to be able to remember where I found what. Actually this entire site started as a way to document the things I learn about Microservices and software engineering, hence all the resource pages and long lists of resources.
I’ve been studying modular software design and microservices in particular for about 2 years. So far this book is the most useful and informative yet. So much of it reaffirms things I have either thought or read about, this book really helps to clarify the topics and assure me that I am correctly understanding things.
Chapter 1 “Escaping Monolithic Hell” is about exactly what it sounds like. It starts out by discussing the horrible realities of monoliths, it also discusses the drawbacks of the Microservice architecture. Monolithic hell and all of it’s problems is what lead me to researching modular software design and ultimately microservices. It only takes one good kick in the balls by monoliths to make you never want to ever build one ever again no matter what you do. This chapter discusses software and architectural patterns, pattern languages and why they are important. This first chapter is a great introduction to the subject of Microservices vs Monoliths.
Chapter 2 goes into details about how to break a monolithic app into microservices. This is one of the most direct explanations I have seen so far. Chris starts out by defining exactly what a Microservice is. It took me a while to finally get to this single answer, so many other sources are wrong or indirect. He discusses how not to create a Microlith or distributed Monolith through loose coupling of services ~page 42 What is loose coupling?
Chapter 2 is very helpful with the discussion on how to find your apps Microservices. This is one of the most helpful discussions I have found on the subject. It starts out by discussing software architectural styles to help you get an understanding of the many ways of doing things. Around page 44 the discussion on Microservice architecture begins with a discussion on how to find the system operations beginning at 2.2.1 bottom of page 45. The next few pages are very handy with their discussion on how to create the domain model from requirements. This chapter discusses breaking down the Domain by Business capabilities and by the DDD approach of Decompose by sub-domain pattern, both end up in the basic same results as Chris points out.
Communication between Microservices is actually one of the hardest things about building a system with microservices. Get it wrong and your app just doesn’t work and you’ve built a big valueless mess. This is a huge chapter starting on page 65 and ending on page 107. This chapter covers pretty much all you need to know about current interprocess communication in microservices. So many things are summed up right here in one chapter, things I had to dig and dig to find slowly, some sources were better than others.
Starting on page 68 the author discusses how to define an API, page 69 leads into evolving an API
One problem with Microservices is that they are distributed. In a distributed system when two or more services need to interact in order to complete an action, you need a plan for when one part of the series fails. When one part of a series of actions fails you need to undo anything any of the successful actions may have done. This is done with something called a Saga.
Pages 110 – 111 Starts the chapter out by telling a nice story to set the scene of the problem that Sagas are meant to address. This is some good insight for anyone not familiar with the situation a Saga solves.
Page 112 Section 4.1.2 The trouble with distributed transactions – points out that the traditional use of distributed transactions has some major downsides and should not be used with a Microservice Architecture.
Page 113 points out that Distributed transactions aka Two Phase Commits are not supported by some NoSQL databases like Mongo and Cassandra or by brokers like RabbitMQ and Apache Kafka. So really they are not compatible with Microservice Architectures unless you are doing it wrong LOL. They are also synchronous by default because the system must wait for all transactions to succeed, in a distributed world you can lose a network connection anytime. Bad news.
Page 114 Section 4.1.3 Using the Saga Pattern to maintain data consistency. This section starts to cover how the Saga pattern works.
Page 115 – 116 cover compensating transactions when part of a Saga fails. This seriously reminds me of functional programming, which I will probably write about some time later. In functional programming you can create functions that execute a series of other functions or not if one of the functions fail. Functional programming is starting to look like it pairs much better with Microservices than traditional OOP. There is a place for both in microservices though, use functional for operations that are non-mutative, use OOP for mutative operations.
Page 117 Section 4.2 Coordinating Sagas – This section quickly covers how a Saga should unfold, it quickly repeats what has been said and leads into the next subject which is Choreography vs Orchestration
Page 118 Section 4.2 Choreography based Sagas – This section covers how a choreography based Saga should operate. The discussion carries over to page 120 Page 119 lists the order for a successful Saga and the order for a failed Saga. Choreographed Sagas communicate with each other via events. Each service that takes part in the Saga listens for events and has an event handler. When a service finds an event it can handle it does so and fires another event for any interested service to also act accordingly. Choreography can lead to tighter coupling because services must know about each other.
Page 120 Reliable event based communication – This section cover some of the drawbacks of choreography based Sagas and continues onto page 121
Page 121 Benefits and Drawbacks of Choreography based Sagas – This small section quickly lists the pros and cons
Page 121 4.2.2 Orchestration based Sagas – This section describes orchestration based Sagas.
Page 123 Modeling Saga Orchestrators as State Machines – This section describes what a state machine is in the context of microservices. It gives a nice example and leads into page 124 with a nice diagram to explain the description of the state machine with microservices. This is a very handy section.
Page 125 Benefits and Drawbacks of Orchestration based Sagas – This section lists the good and the bad.
Page 126 Section 4.3 Handling the Lack of Isolation
Page 127 section 4.3.1 Overview of Anomalies – This section covers issues such as lost updates, dirty reads and fuzzy/non-repeatable reads
Page 128 section 4.3.2 Countermeasures for handling the lack of isolation – This section starts by mentioning some of the issues and counter measures then continues by explaining each type
Page 128 The structure of a Saga – This section has useful information about how transactions should work together throughout the lifetime of a Saga.
Page 129Â Countermeasure Semantic Lock – This carries on to page 130 describing how to use fields in a table to mark at what stage a Saga is currently in. This is a pretty simple concept.
Page 130 CounterMeasure: Pessimistic view – Talks about reordering the steps of a Saga to help prevent some issues.
Pages 132 – 145 The Design of the Order Service and the create order Saga – These pages show an example of how a Saga should work complete with a Java code example using the authors Eventuate Tram Framework. Good information on these pages.
Page 147 Section 5.1 Business Logic organization pattern – Mention inbound and outbound adapters for handling requests. This section mentions developing business logic with OOP or procedural approaches, it totally avoids a functional approach. I personally feel a mix of OOP and Functional is best. Very few people are familiar with Functional programming, but it is something I am getting deeply into. After many years of OOP I am simply tired of all of the BS boiler plate it causes. OOP causes too many pieces in a puzzle. Scala’s OOP and Functional abilities really pulled me to it, the more I learned it the more I hated Java. I seriously, seriously hate Java to the point my hatred forced me to Scala. I don’t feel like writing a full god damn paragraph of irritating boilerplate code to instantiate a single god damned object, thank you very much Java. When you see the amount of Java vs Scala to get work done you will grow to hate Java too. Scala is fairly hard to learn though because you can do so many things.
Page 149 Section 5.1.1 Designing Business Logic using the Transaction Script Pattern – This section explains how the transaction Script pattern works.
Page 150 Section 5.1.2 Designing business logic using the Domain Model pattern – This section starts the discussion about creating the business logic with Domain Driven Design principles. I am determined to learn how to use DDD concepts with Functional programming.
Page 151 Section 5.1.3 About Domain Driven Design – This section quickly covers some minor basics of DDD
Page 154 Section 5.2.2 Aggregates have explicit boundaries – This section gives the definition of an aggregate and continues to explain aggregates with a diagram of what an aggregate is on page 155
Page 155 Aggregates are consistency boundaries – This describes nicely how an aggregate controls the business invariants.
Page 155 Aggregate rules – This section lasts a few pages and covers the rules aggregates should obey.
Page 156 Rule #1 Reference only the aggregate root – Talks about how external services should only be able to accesss the aggregate root of an aggregate. Aggregates are similar to Microservices and each has a root which is basically it’s API
Page 156 Rule #2 Inter-aggregate references must use primary keys – This is a nice section that explains how aggregates are separate objects and each should be referred to by an ID as in a primary key instead of an object reference like creating a new object. This adds to improved loose coupling between aggregates.
Page 157 Rule #3 One Transaction creates or updates one aggregate – This section quickly covers why transactions should only update one aggregate and if you need to update more then you need to use the Saga pattern from chapter 4.
Page 158 Section 5.2.4 Aggregate granularity – This section basically covers Large vs Small aggregates it gives some pros and cons and has a nice diagram.
Page 159 Section 5.2.5 Designing business logic with aggregates – This section has a nice diagram showing the design of a service based on aggregates.
Page 160 Section 5.3 Publishing domain events – This section covers domain events. Domain events are things that have happened to an aggregate such as a state change. This section notes that changes are published as events for any interested party to consume for whatever purpose.
Page 160 Section 5.3.1 Why publish change events? – This helpful section lists reasons to publish domain events. There are a lot of good reasons listed here, too much to type out.
Page 161 section 5.3.2 What is a Domain event – This section defines what a domain event is and gives pointers on how you should create them. Domain events usually have an id attached to them
Page 161 Section 5.3.3 Event Enrichment – This useful section talks about enriching events with other metadata that future consumers may need. This is something I was thinking about doing with functional programming techniques as well. Basically I was thinking of passing a list of functions with the data they need, much the same as Sagas work, to a function. Much of what I am reading about Sagas and communication remind me of Functional programming techniques such as functors and monads. Why not send a list of functions to a function and let it handle the happy and sad paths? Sounds like a Saga to me. The more I read about functional programming the more I like it, it is easy like Math.
Page 162 Section 5.3.4 Identifying domain events – This section spills over onto page 163. It discusses Event Storming and gives a quick overview of what it is. I have an entire resources page dedicated to this subject.
Page 164 – 165 Section 5.3.5 Generating and publishing domain events – This is a nice section that covers the process of creating and publishing domain events.
Page 166 How to Reliable publish domain events? – This section repeats information from chapter 3 about using Eventuate Tram.
Page 167 Section 5.3.6 Consuming Domain Events – Domain events are published as messages to a message broker like Kafka for other consumers to find and act upon. This section mentions using Eventuate Tram instead of directly interacting with the Kafka API.
Pages 168-169 Section 5.4 Kitchen Service Business Logic – This section discusses the logic of one of the Services in the books imaginary app. Page 168 describes the diagram on page 169 which shows the structure of the Kitchen service pointing out the Aggregate and all the moving parts.
Page 169 Section 5.4.1 The ticket Aggregate – This section covers how aggregates should work. There is some useful information here covering the hows of aggregates.
Page 170 Structure of the Ticket class – talks about the ticket class and makes some good points about using object ids instead of passing objects because microservices are distributed.
Page 170 Behavior of the Ticket Aggregate – Shows the Ticket Aggregate class and describes how it works. This section describes the states of the Ticket aggregate aka it’s state machine. This is a very useful example.
Pages 173 – 174 Describe the different working parts of the imaginary app with a really nice diagram showing how all of the pieces of the Order Service work together to form a microservice.
Page 175 Section 5.5.1 The Order Aggregate – Covers the order aggregate giving a nice example and thorough walk through of the Order Aggregate and how it operates. There is a diagram to accompany the discussion which is helpful. This diagram shows examples of the Aggregates Value Objects. This is helpful to see how it relates to the subject. The discussion carries over to page 176 where it gives some example code of the Order Class.
Page 176 The Order Aggregate State Machine – This section gives a useful example of how a state machine works in and a nice diagram on page 177 that shows part of the state machine model for the Order Aggregate.
Pages 177-180 The Order Aggregate’s Methods – this long yet useful section covers the methods of the Order Aggregate and show a few pages of example code as part of the discussion.
Page 184 Section 6.1 Developing business logic using event sourcing – this section gives a quick definition and description of event sourcing. This section is useful. It talks about some of the pros and cons of Event Sourcing in microservices. Event sourcing pattern link
Page 185 Section 6.1.1 The trouble with traditional persistence – This section quickly covers the problems with trying to use the traditional data persistence pattern with microservices architectures. The next few sections and pages elaborate.
Page 185 Object-Relational impedance mismatch – This basically means that your object in your code doesn’t match the schema of your database. The funny thing is this mismatch goes away with properly designed microservices. These microservices will more closely match the structures of the original monolithic database. Basically what used to be tables becomes microservices where some tables live together under one microservice.
Page 186 – covers the rest of the trouble with traditional persistence including Lack of Aggregate History which means that you can’t figure out how your object got into the state it is because with traditional persistence you simply update table fields to represent the objects changed states. This makes auditing hard
Page 186 Implementing audit logging is tedious and error prone – This section discusses how audit logging works for tracking things like changes a user has made to an object which change it’s state etc. About the same as Aggregate History.
Page 186 Event Publishing is Bolted on to the Business logic – This quickly covers the fact that Event publishing wont work very well with the traditional CRUD persistence pattern because things get out of sync.
Page 186 Section 6.1.2 Overview of event sourcing – This is the best description of Event Sourcing I have seen so far. “Event sourcing is an event-centric technique for implementing business logic and persisting aggregates. An aggregate is stored in the database as a series of events. Each event represents a state change of the aggregate. An aggregate’s business logic is structured around the requirement to produce and consume these events.”
Page 186 Event Sourcing persists aggregates using events – This section has a nice diagram of a table with fields that demonstrates saving events to a database. It covers saving then replaying the events to rebuild the aggregate/object. This is an important point because it points out how persistence in a Microservice Architecture is different from monoliths. Event sourcing allows your application to spin up more microservice nodes to handle more traffic when needed. This is done by replaying the events of objects, while each new microservice node handles a different section of the work from the events list.
Page 188 Events Represent state changes – this nice section covers what kind of data events should contain. All events are different and each needs to carry different information for various reasons.
Page 189 Aggregate Methods are all about events – This section explains that to use event sourcing you must refactor command methods into more than one method to match the event states.
Page 191 covers the process for creating and updating aggregates by selecting and applying events.
Page 191 Event sourcing-based order aggregate – This section gives an example of the the use of Event sourcing by showing some example code of the Order class refactored to use Event sourcing. This is a very useful example.
Page 194 Using Polling to publish events – This is when an event publisher polls a table for events and publishes them to the broker. This section discusses the problems with this approach and the next few sections discuss a solution.
Page 195 Using Transaction log tailing to reliably publish events – Doesn’t say much here other than log tailing is more reliable and will be explained better later.
Page 195 Section 6.1.5 Using Snapshots to improve performance – This section explains how snapshots reload aggregates state efficiently. Basically instead of loading all of the events for a particular entity and replaying them all, you load a snapshot from a point in history and replay from that point. Not covered in this section ->This is also useful if you have a service with multiple nodes, that is a service running the same code on multiple cloud instances for example. This way as the system needs more resources it can spin up new nodes in the cloud and have them start from their own snapshots for the entities they recreate the state of.
Page 196 Section 6.1.6 Idempotent message processing – This section briefly covers the fact that event messages should only produce a result once and how to enforce this. This section talks about Eventuate Tram more.If you are using Java this sounds like a good solution. I’m using Scala so I could maybe use Eventuate by implicit conversion, but I am interested in AKKA, KAFKA, Lagom, Cassandra, Spark. Scala lets you use a very large amount of Java though. When I get bored maybe I’ll try eventuate with Scala and write an article.
Page 198 Section 6.1.7 Evolving Domain Events – This section makes important points about some of the main reasons your events may change over time and some of the things you can do.
Page 199 Section 6.1.8 Benefits of Event Sourcing –Â This section covers a few of the great benefits of Event Sourcing like Reliably publishing domain events, Preserving the history of an aggregate, Avoiding Object/relational mismatchs and providing developers with a time machine. Event sourcing provides some awesome benefits.
Page 200 Section 6.1.9 Drawbacks of event sourcing – This covers some of the drawbacks such as a harder to learn programming model, it has the complexity of a messaging based application, evolving events is hard, deleting data thanks to GDPR is harder, querying the event store is harder.
Page 201 Evolving events can be tricky – This short section talks about the complications that can occur when you have made changes to an event.
Page 201 Deleting Data is Tricky – This section mentions using encryption of private data with a unique key per user so that you can effectively delete personal user data to be in compliance with GDPR. This is some handy information.
Page 202 Section 6.2 Implementing an event store – This section talks about event storage and how they should operate. It then lists a couple of event stores, Event Store, Lagom(for Scala and Java this is what I’ll use), Axon( for Java) and Eventuate( for Java) If I were using Java I’d go with Eventuate it sounds great, if you are using Java try it to learn some things. You should research and decide what is best for your language.
Page 203 How the Eventuate local event store works – This section talks about how the event store works theoretically in a way you can implement on your own without Eventuate. I’ve still got to dig into how Lagom does this. One of my goals is to understand Lagom before I use it to build a large system. I’m older now. I’ve made quick decisions in the past and misunderstood how something operated and made a ball of mud.
Page 209 Section 6.3 Using Sagas and Event Sourcing together – This section talks about some of the complexities encountered when using Event Sourcing with the Saga Pattern.
Page 210 Section 6.3.1 Implementing choreography based sagas using event sourcing – This short section explains that choreography based Sagas in an Event Sourced system is harder to implement and why. This section has useful information.
Page 211 Section 6.3.2 Creating an Orchestration based Saga – This section carries on to page 212 and explains how a microservice system that wants to implement Orchestration based Sagas should go about doing so. It also makes a comparison and gives information about using an RDBMS vs a NoSQL database. There is a nice diagram explaining the process on page 212
Page 212 Idempotent Command Message Handling + Atomically sending reply messages – This section has some really useful information related to how Saga participants can communicate with the Saga Orchestrator.
Page 216 Section 6.3.4 Implementing Saga Orchestrators using event sourcing – This section gives some good information about creating Event sourced Saga orchestrators.
Page 216 Sending command messages reliably – This section has some great information about the process that is used to send command messages in an Event sources orchestration based system.
Page 218 Processing replies exactly once – This section basically summarizes the process of idempotent message handling.
Page 222 Section 7.1.2Â Overview of the API Composition Pattern – This section covers how the API Composition pattern has the methods of the API query the needed services and build up a response. Link to the pattern.
Page 224 Section 7.1.4 API Composition design issues – This covers some of the design issues when implementing the API Composition pattern such as deciding which component will be the API composer and how to write efficient logic. This section makes very important points. One thing I thought about while reading this section is if you are using REST or RPC, what if one of the services that need to be queried is failing? Then your entire query is holding up resources. What if you used the same process of event sourcing to build the query so that nothing hangs up. Have a query orchestrator use a Saga like pattern to build the query.
Page 227 Section 7.1.5 The benefits and drawbacks of the API composition pattern – This section covers the pros and cons of this pattern such as increased overhead, reduced availability and lack of transactional data consistency.
Page 228 Section 7.2 Using the CQRS pattern – Link to CQRS pattern. This simply explains some of the reasons to use the CQRS pattern.
Page 231 A challenging single service query: findAvailableRestaurants() – This section has some useful information about choosing the correct database to store your data for query purposes.
Page 232 Section 7.2 Overview of CQRS + CQRS Separates Commands from Queries – These sections give an overview and definition of CQRS. It continues to page 233 with a nice diagram that demonstrates the process. This is a very useful section.
Page 235 Section 7.2.3 The benefits of CQRS – This section lists the benefits of CQRS and has four sub-sections that go into deeper detail on the following *Enables the efficient implementation of queries in a microservice architecture * Enables the Efficient implementation of diverse queries * Enables Querying in an event sourcing based application * Improves separation of concerns.
Page 236 Section 7.2.4 The Drawbacks of CQRS – this section lists some of the drawbacks in two sections *More complex architecture * Dealing with the replication lag These sections contain very useful information.
Page 237 – 239 Section 7.3.1 Choosing a view datastore – This section covers some of the aspects you need to consider when choosing a database for your CQRS views/queries. It notes some of the various strengths and weaknesses of different database types.
Page 239 Section 7.3.2 Data Access Module Design – This section makes some good points about DAO classes and how they should handle events. It covers Idempotentcy with some good ideas on how to implement it. It finishes by talking about how to deal with eventual consistency in a query view.
Page 241 Section 7.3.3 Adding and updating CQRS views –Â This section has some good information about the problems you will face when adding or updating CQRS view modules and gives some example solutions.
Page 242 – 252 Gives an example of implementing CQRS views using AWS DynamoDB. There is a lot of useful information in these pages.