Skip to main content

Posts

Showing posts from 2016

DDD - Events

The act of something happening is one of the most crucial aspects of implementing Domain Driven Design (DDD). I missed the importance of domain events when first exploring DDD.WhyMost requirements come in the form when something happens, do this. Something in this case would be an action, and this would be the result taken afterwards. Most domain events can be discovered when requirements use this sort of language.Another important consideration is that most requirements are evolutionary. They are often added as the feature is developed. What may start off as a single piece of behaviour, may evolve into something much more complex. Events allow this evolution in a decoupled manner.ExampleWhen a blog post is published, update the authors statistics. In code this may have a signature similar to:The publish method is responsible for the publishing of the post. This entity holds responsibility for the pre-conditions and post conditions of such action. Also the method takes a domain servic…

POODR Highlights Part 2

Two other stand out topics from POODR were the use of tests and inheritance. The first set of higlights covered dependencies and arguments.TestsA conclusion that I agree with is that in general most programmers write too many tests.. A great quote in the book sees tests (as) the canary in the coal mine; when the design is bad, testing is hard. Sadly too many poor tests are often written. Examples such as property or construction tests, framework tests or tests that are coupled to the implementation are all common problems. Instead we should aim to get better and more value out of our tests by writing fewer of them, but of higher quality. In short test everything once and only in the proper place. A first step is to simply focus on the ROI that tests give, and focus on the high risk areas.The test categories are broken down into two core types of tests.Incoming Public Messages (public API)Outgoing Public Messages (To public API of another object)State based tests should be used for inc…

POODR Highlights Part 1

Practical Object-Oriented Design in Ruby or POODR is clearly a book about Ruby development, however the odd aspect is much of the concepts apply to other languages. In fact I've taken these ideas and used them both before and after reading the book in other dynamic languages and even static languages such as C#. In summary the book is well worth a read, even if you don't do Ruby development full-time.A few of the highlights for me will be spread out across the following posts.DependenciesThe author takes a firm stance on dependencies. Anything that cannot be controlled by the class itself should be protected from change. In other words a message sent to self/this is preferred than directly interacting with a dependency.I've followed this pattern in the past, but the seeing the justifications for the benefit of this has made me realise the importance of such a practice. In the first example the publish method directly knows about the twitter feed it must interact with. In t…

The New Guy

Everyone is new at some point. No matter your experience level. You're either new to the team or new to the business. Being the new person is both a blessing and a curse.You're NewWhen you're new you come with no baggage. You're full of questions and curiosity.Why do we do it this way?Isn't there a better way of doing this?Have you considered this instead?These are all great questions for new starters to ask, and for teams to hear.You Have a New Team MemberWhen you have a new team member you gain someone with a fresh perspective. They're full of questions and curiosity. Rather than history, they'll be open to new and fresh challenges. A new member can ask you to question current practices. It is very easy to overlook problem areas only until someone with a fresh outlook arrives.How to be NewThere are two roles a new team member must play.LearningChallengingThe learning phase should involve questions, shadowing and pairing. The goal is to learn about the sys…

Constant Object Anti Pattern

Most constants are used to remove magic numbers or variables that lack context. A classic example would be code littered with the number 7. What does this refer to exactly? If this was replaced with DaysInWeek or similar, much clarity is provided. You can determine that code performing offsets would be adding days, rather than a mysterious number seven.Sadly a common pattern which uses constants is the use of a single constant file or object. The beauty of constants is clarity, and the obvious fact such variables are fixed. When a constant container is used, constants are simply lumped together. These can grow in size and often become a dumping ground for all values within the application.A disadvantage of this pattern is the actual value is hidden. While a friendly variable name is great, there will come a time where you will want to know the actual value. This forces you to navigate, if only to peek at the value within the constant object. A solution is to simple perform a refactor …

New and Shiny Things

There is risk with upgrading anything, be it language, framework, library, OS or third parties.In the past I was rather gung-ho about upgrading. New version out? We need it. In fact, this need is often a want. The new version often seems better. Developers seem addicted to the latest and greatest.One of the best, but also one of the worst problems with software development is weekly there is something new to use or try. Keeping pace is impossible.Internet Echo Chamber EffectIf you look at a news article on the release of something, you feel as if you are the only person not using it. Everyone is is using it, we need to as well.In fact this is quite the opposite case. A site about the latest web framework will seem as if everyone is using the framework apart from yourself. This is known as the Internet Echo Chamber Effect.Wait for a PatchWise advice I received and saw others follow was the minor or patch adoption. If version 2 comes out, wait for 2.1. Let others find the issues and wai…

Past Mistakes - ORMs and Bounded Contexts

Sticking with the theme of documenting past mistakes, it's worth expanding a real life scenario where I was unaware of the use of bounded contexts and fully understanding the tools you use.Ignoring a Bounded ContextA fellow developer set upon a quest to rid numerous projects of duplicated records, which was effectively the active record pattern. This was a huge under taking split across hundreds of thousands of lines of code, over numerous separate projects. Close to completing the task I assisted and finally the shared library containing a single record for each type was complete. Each project now referenced the shared copy. This was versioned as each build was completed.For a while this worked with no problems. It certainly felt nice to see the reduction in duplicated code. Sadly sometime later myself and another developer made a seemingly innocent change. In terms of relation, the change was as far removed from the production error that we had just been alerted to was. There wa…

Test Your Live System using Live Service Tests

Traditionally there are three categories of functional tests.AcceptanceIntegrationUnitThis is often refereed to as the testing pyramid. Unit tests form the bulk of your suite, followed by a smaller subset of integration tests. Acceptance tests that cover features should be the tip of your testing strategy, few in number. These are great but there is a missing suite of tests - live service tests.Live Service TestsAcceptanceIntegrationUnitLive Service Tests.The role of live service tests (LST) is to test the live system against the production environment and configuration. LST would be fewer in number than acceptance tests. Unlike acceptance tests, these should run constantly. Once a run has completed, kick of a new test run. This will require a dedicated machine or piece of infrastructure, but the value provided is well worth it.LST should focus on journeys instead of functionality or features. In contrast to acceptance tests a user journey would be the core purpose of the system. Fo…

Why You Should Do Code Katas

Code katas are simple exercises that are meant to be repeated. They are great for learning a new language or tool. The goal is to learn something, not to complete them. In fact, if you don't finish a kata that is perfectly normal as long as you take something away. The beauty of code katas is they are small enough to be repeated and possibly completed within small time slots.TakeawaysBeginner or expert there will be something you can learn or take away. Beginners should take away language skills, tooling tricks and more. This is furthered when pair programming.Experts should be inclined to try new solutions rather than rinse repeat. Instead of solving the problem in the manner you do 9-5, try something completely new. Solving a kata ten times the same way is a waste. Instead solve it once, ten different ways. In short, experiment in code katas, not your production code.Going FurtherSadly a small minority seem such simple exercises as below them. No one is above doing a kata. Const…

I Need to Stop Misusing Divs

I a certainly not a skilled or expert front end developer. While I'm more than capable of creating pages I lack any design magic to make them look half decent. Despite this one area where improvement can be made is in my markup itself.Over the past few months I've spent most of my time getting to grips with recent additions and changes in the HTML5 and CSS3 space. During this one area stood out, my misuse of the division element or <div>.Before the addition of the newer elements pages nested with div after div was normal. However this is no longer the case. From this point onwards I will be ensuring that every time I introduce a div element I question whether a more appropriate element should be used. The HTML div element (or HTML Document Division Element) is the generic container for flow content, which does not inherently represent anything. It can be used to group elements for styling purposes (using the class or id attributes), or because they share attribute values…

Anaemic Domain Models and Code Smells

An anaemic domain model (ADM) is considered a code smell in many cases. An ADM is present when you have a entity representing your domain, but void of any behaviour. Any logic is separate and operated upon in isolation. Such domain models can be thought of as simple property bags, plain old language objects or DTO's.Code SmellsWith an ADM your behaviour ends up split across many domain services instead of being grouped with the data it operates upon.As the domain and your understanding evolves, the problem an ADM introduces can get worse as more and more domain services are added.A complex domain or one that evolves will end up paying a price. Converting to and from what looks like a domain model, only to perform domain logic separately is quite redundant. Why not ditch the domain model altogether? If you have a simple problem, a simple solution such as a transaction script may very well do the job.Simple Problems - Simple SolutionsSometimes you don't have a complex domain. In…

UI Composition Techniques for Services

When using services be it SOA, microservices or some other hybrid approach, at some point you will need to display an aggregation of data onto a UI. This simple task can actually involve some complexity and hidden pitfalls.As an example, this blog could be powered by three independent services. A comment service, a post service and a archive service. Displaying this content on the page could involve a few different approaches both with pros and cons. Each vary in terms of benefits and complexity.Service CompositionServer Side CompositionBackends For FrontendsFrontend UI CompositionService CompositionComposition within independent services should be avoided at all costs. In these cases service A invokes service B which invokes service C, which has a dependency on A and so on. The problems such composition introduce defeats any benefits that a service based approach brings. In short composing data in this manner will lead to problems.Server Side CompositionInvoke each service behind a s…

Notes on Building and Deploying Software

Builds and DeploysIdeally a build and deploy should be a single step, included within the check out of the repository. Additionally the build should include and install pre-requisites if missing. You can safely assume the target OS is at least configured, but any missing packages should be installed as needed.The core steps regardless of platform or technology follow a common pattern. A number of these steps can be performed asynchronously. For example, it is possible to run a suite of tests in parallel, rather than individually. This can save massive amounts of time. As a first approach perform all steps synchronously, only adjusting once stable.Compile/Lint - SyncRun Unit Tests - AsyncDeploy - AsyncWarm up (cache hits, web server)Data (run migrations)ConfigurationHost EnvironmentRun Integration/Acceptance Tests - AsyncThis whole process should be executed regardless of environment. A local developer machine only differs to production in terms of topology. If you cannot execute the e…

Ten Lessons from Rewriting Software

It Will Take A Lot Longer Than EstimatedIts navie to actually think this but if a system has been in production for say five years, expecting to reproduce it in five weeks is not possible. You may be able to get 80% of the core functionality done, but the remaining 20% that was added to, iterated and stabilized over the remaining five years is what will destroy any form of schedule.If your estimate exceeds three months, you need to reasses what you are doing by breaking down the work, or changing plan. The bigger the estimate, the bigger the risk.Deploy Incrementally Via CIIf you aren't deploying to a live environment as soon as possible, any future releases are destined to be failures, troublesome or just plain difficult.Soft releases and feature toggles should be used to aid constant releases.Morale Will Drop The Longer It Goes OnProbably the biggest and most surprising realization is the drop in personal and team morale.If you miss a "deadline" or keep failing to ship…

DDD - Bounded Contexts

A single domain can grow large when applying Domain Driven Design. It can become very hard to contain a single model when using ubiquitous language to model the domain. Classic examples prevalent in many domains would be Customer or User models. A bounded context allows you to break down a large domain into smaller, independent contexts.In different contexts a customer may be something completely different, depending on who you ask and how you use the model. For example, take three bounded contexts within a typical domain that allows customer administration, customer notifications and general reporting.ExampleNotification ContextA customer is their account id, social media accounts, email and any marketing preferences. Anything that would be required to uniquely identify a customer, and send a notification. + Id + Email + Marketing Preferences + Social Reporting ContextWhen reporting customers are nothing more than statistics. A unique customer ID is more than enough j…

Given When Then Scenarios vs Test Fixtures

There are two common ways of writing automated tests which apply from unit to acceptance tests. These are typically known as test fixtures and Given-When-Then scenarios.Test FixtureTraditional method of writing tests.The common JUnit/NUnit approach. Other languages have very similar concepts.Single test fixture with multiple tests.Test fixture is usually named after the subject under test.Can grow large with many test cases.Works well with data driven tests.Suited to solitary tests such as integration tests where GWT syntax would be verbose or hard to include.ExampleGiven-When-ThenBehaviour driven approach (BDD style).Made popular by tools such as RSpec.Single test fixture per behaviour.Test fixtures named after the functionality being tested.Often nested within other test fixtures.Smaller test fixtures but more verbose due to fixture per functionality.Easy to see why a test failed due to naming convention - assertion message is optional.Suited to sociable tests where the focus is on …

Your Job Isn't to Write Code

Solving problems is the role of software developers first and foremost. The most interesting aspect is that in many cases it is possible to perform this role without writing a single line of code.Low TechI once worked with a digital dashboard which monitored applications. One of the yet to be implemented features was a key to highlight which each chart related to. During this period many employees would ask which graph related to which feature. The solution was a few weeks a way so as a temporary fix I stuck a post it note to the screen. This was by no means the solution, but it was good enough for the time being. The questions went away and eventually the dash was updated to include a digital version. Total lines of code? Zero.Problem Solving without a ComputerA common experience that many developers encounter is solving a problem while not actually at the computer, programming. In fact this technique of simply taking a break such as going for a walk can yield some impressive results…

Foreign Key Constraints and Microservices

Database constraints when used in relational databases are great. They ensure data integrity at the lowest level. No one would argue against using them in practice. Essentially constraints can be thought of as assertions against your database. Rules such as requirement, default values and foreign key constraints double check your use of the database. This ensures your application is interacting in a sane manner. Databases often out live applications therefore constraints also ensure integrity long after the application has been replaced or modified.Distributed SystemsDistributed systems change how foreign key constraints should be considered. As distributed systems own their data, each piece of data that is mastered by a single service should ensure integrity via foreign key constraints. However outside of this boundary the use of foreign keys should be avoided. This sounds disturbing at first. Especially given the traditional approach of a single system backed by a single database.E…

Past Mistakes - Out of Process Commands

Some of the best lessons you can learn are from failure. I figured a series on mistakes I've made in the past would highlight where I went wrong and more importantly what to remember going forward. These real life examples vary from my early days of programming all the way up until present day.I once wrote a feature that sent email to users on their behalf. On localhost this was fine. Fast, stable and good enough to get the job done.Despite early successes, under load in a live environment, things were different. Sometimes the process would out right fail, requiring the user to retry. Other times it would be slow to process. This meant the users browser would hang while the email was being sent.It was hard to replicate these problems. The actual code itself was pretty simple, there was nothing to optimize it seemed.MistakesThe core mistake was performing an operation out of process from within the life cycle of a HTTP request.When sending the email was slow, the HTTP response was …

You Rarely Need Custom Exceptions

Implementing custom exceptions usually gives a hint as to why you rarely need custom implementations. They are often nothing more than sub classes where the only difference is the type name and containing message.In this C# example there is a lot of code for nothing. When checking logs or handling bugs you will read the message and the stack trace. The first line containing a bespoke name rarely matters. Within the code throwing the exception very little context is gained from the type of exception - instead most of the details will be present within the error message.Each custom exception you introduce adds overhead from source lines of code (SLOC) to compilation and execution.AlternativeSimply do not create custom exceptions except in the rarest of occasions. Instead rely on the standard library of the language you are using. Take Python as an example [Video]. ~200,000 lines of code yet only ~165 exceptions. This works out at about one exception for ~1200 lines of code.If battle har…

X% of Configuration is Never Used

Code configuration is essentially for the likes of URLs, credentials or other per deployable settings. Sadly configuration seems to fall into examples where there is simply too much configuration, or the system has so many configuration points the actual code becomes far too complex for its own good.Too Much ConfigI once worked on a system with in excess of six hundred different configuration points. In reality all but a handful of these would ever actually need changing. Most configuration is added to enable anyone to make the change. Ironically if these configuration points do need changing, developers need to do it. The business or non technical individuals will never change settings. In this scenario you would need to actually test all six hundred different combinations of configuration. 1 on, 599 off, 2 on, 598 off and so on - this is not ideal nor realistic.Configurable Systems are ComplexOne of the earliest project mistakes I can remember involved creating a system that could b…

Legacy Code is Just Code

Try and define legacy code. Working Effectively With Legacy Code states it is simply code with no tests. This is an almost perfect definition, however it is quite easy to have code that is covered by automated tests, yet is still considered to be legacy. Poor quality, or missing test cases can provide a false sense of security.Legacy in the Real WorldLegacy code is scary to change or work with. Typically it is stuck using an old language or framework which is too expensive to upgrade. Most notable legacy code is often considered old. Developers or teams that no longer exist wrote it and have long since moved on. Hence legacy code is often ignored or over looked by the wise. To be blunt, most developers consider legacy code to be crap.Just CodeIn the end legacy code is just code. It should be treated and given the same amount of respect as your new and shiny solution. In fact legacy code is more than that, it's proven. Unlike clean code you have stagnating in your repository, legac…

Dependency Injection for Common Global Dependencies

The use of singletons can often be replaced by simply adjusting scoping of objects. The vast majority of dependencies fit this pattern, with a few exceptions such as DateTime instances, or logging.Sometimes you just need these dependencies everywhere. You can find yourself passing these dependencies down into the deep depths of your code base. Such changes are often dangerous, time consuming and undesirable.DateTimeFor a while the use of some date/time abstraction was my default approach to handling dates and times. This fake clock or calendar instance when combined with DI at the lowest level does actually work. However if we stop and think about the abstraction it is clearly unnecessary in many cases. Unless your domain is dealing with date and times explicitly, you don't really need an abstraction. In other words, other than the system where the code is running when or why would you provide a different implementation?The approach taken as part of the example within the Dependen…

Project Setup Tax

With microservices gaining popularity, one consideration prior to adoption is new project setup. In fact this statement holds true for any new project that you decide to create.Each new project requires at a minimumSource control - somewhere to actually store the code.A project base - API, executable, library, application etc.Users, accounts and permissions.Build configuration - in order to compile, package and run tests.Deployment and installation - to a production like environment.Remember this is all before you write a single line of code.Automating as much of this away does help. Templates, conventions, containers or similar can assist. Still nothing is free. This all requires maintenance regardless of how you choose to optimize the creation of a new project.When weighing up decisions about a separate project, always factor in the project setup tax. In my experience this tends to take longer than expected. Often it is very easy to forget various project conventions, configuration …

Pulling the Plug on Date Time Parsing

Date/time logic is hard. Throw in time zones along with daylight saving and it's even harder. Recently a suite of tests that had happily been running for months started failing. There were no code changes and all the tests were somehow related to date/time ranges.Despite this the production code was functioning as expected. It turns out the API was explicitly setting the locale to use en-GB. However the suite of tests were not. The fix was simple. Prior to the test fixtures executing, explicitly set the locale. In order to test this assumption and see the tests pass, a temporary change on the development machine was required.The locale was set on the development machine to another region. In this case setting to en-US was enough to cause the tests to fail. After the code change the tests passed. Any locale can be used as long as the date format differs.This idea is pretty easy, and is very close to my technique of pulling the plug on automated tests. The test suite can now be run …

Best of Breed

Spikes are one of the best ways to aid the design of software. In some cases spike solutions can open more questions than they solve. The use of a technique known as Best of Breed can assist when this arises.Rather than producing a single spike, produce several. Either individually or with other developers working on a spike each. Each solution can then be compared and contrasted. The best parts of each solution can then be combined. Best of Breed is named for its likeness to genetics where the best genes win out for future generations as part of the process of evolution.ExampleSpike solution A has an excellent way to handle future requirements due to the open and closed approach taken. Solution B solves the data access problem in an elegant manner. Both solutions have good components. Simply combine the solutions into a single approach. This results in code that contains extensibility and good data access patterns.BenefitsNeither standalone solution would have been as good as this hy…

Singleton's and the Singleton Lifestyle

The death of testability and the lack of isolation make the singleton pattern a relic of times gone by. Rarely have I had a real need to code a singleton since my first year of university. Most decisions to use a singleton boil down to scoping issues.SingletonAssume a game requires a single instance of a rendering component. In this example configuring and initialising the renderer may be expensive. We only want to do this once.While this singleton renderer solves the problem of instantiating more than once it suffers from the fact there is only ever one instance. If we want multiple renderers such as a console debugger we are out of luck. Testability is also lost. If we wish to exercise the Game, we need to provide and use a real rendering component.Static ClassesOr class instances give you the same advantages and disadvantages of singletons. You only have one instance and you can access it easily. One big difference is that unlike singletons you cannot provide static instances as ar…

Eating your own Dog Food

Also known as dog fooding. It's an odd term, with roots dating back to 70's adverts and the even more bizarre. In software development the idea is simple. Use the software you produce to make it better. This can be taken to the extreme with examples such as Notepad++ being built with Notepad++, or the Github team using Github internally. These examples mean the product is as good as it can be from real life use.API'sDog fooding works great for APIs. When the boundary of a system is an API building a fake test UI is a wise move. This integration acts as if you were the user. If you can solve the basic uses cases that your integrators need you can be confident the API is fit for purpose. Integration highlights problems and areas for improvement. Building a test UI is a very easy step to carry out which is also useful for demonstrating and documenting the API to others.The danger of not eating your own dog food when producing APIs is detachment from what your users will be tr…

Write Assertions First

Writing a test as part of the TDD process is simple.ArrangeActAssertMany individuals recommend the process be reversed. Write assertions first. Then write the steps to perform the action. Followed by the required setup to complete the action.ArrangeActAssertSimplicityYou will write just enough of the test to do the job. Its not far from doing TDD on the test itself. Using staticily compiled languages you would see compile time errors while performing this step. As you are writing the test in reverse this is normal and expected. Most text editors or IDE's can ease this process.Implement just enough of the test to do your job. The opposite of this is large, copy/paste tests that require lines of setup code that can safely be removed or reduced.MeaningYou end up naming variables with more meaning. With a traditional approach variables can lack true, descriptive names. They are often called result or similar. By working in reverse you force yourself to think of what you are asserting …

Why you need a Developer Diary

After eighteen months of use, I can safely claim how useful a a developer diary is, and why you should start using one if you don't already. ChangesUsing a single file grew too large as expected. Instead each grouping is allocated an individual file. While some of these are small, the ability to navigate easily is not lost. The simplest thing to do here is just point a browser at the directory. Navigation and searching is then built in. Each week I actively split the main file file into separate files or merge to existing content.UsesI'm increasingly finding regular needs and uses to refer back to notes. In some cases it is quicker than searching online, simply hit the bookmark and start typing.Adding notes works great when reading books or watching videos. All content recorded ends up in the same location.Do ItKeeping a developer diary is without doubt one of the most useful changes to my development process. Encouragingly others are doing similar things too, but under slight…

Gaining Ten Extra Hours a Week

For a long time my work life balance has gone through phases. Some weeks I would spend hours after work writing code. This would exceed to well beyond midnight in some cases. This phase was not sustainable but it appeared to be the norm.My other hobbies such as reading and gaming were also neglected. These too suffered from weeks of focus, followed by quieter periods.Over the course of a typical year this cycle would generally balance out, but never feel comfortable. There were always areas that lacked focus. One of my common complaints which I have shared with many other developers is around the lack of time to do anything additional to the day to day job. There always seemed to be a sacrifice.MorningsThe book Soft Skills recommends taking the first hour or two out of your weekly day to focus on important goals. This piece of advice was not going to work for me I thought. I was not a morning person.Sometime after I discovered an article from the Art Of Manliness (AoM) which gave tips…

The N+1 Problem

The N+1 problem is when multiple queries are executed against a persistent store when a reduced amount could serve the same purpose. This degrades performance, uses more memory and can cause complexity to be added to the code that processes the results. Most sources of the problem come from the poor use of ORMs or developers thinking procedurally instead of in terms of how the underlying database operates.ExampleConsider a collection of posts that each contain zero or more comments. Post Comment Comment Post Comment Comment Comment Comment Comment Post To retrieve a selection of ten posts including their comments, one option would be to query all posts then perform a query for each individual posts' comments. This would result in a total of eleven queries. While this solution works it is far from ideal. Disturbingly this solution is easily introduced when developers execute queries against databases using loops or misconfigured ORMs.SolutionsSolut…

Sproc vs ORM vs Inline vs Polyglot

With relational databases the common data access patterns tend to fall into three core options.Direct access via inline SQLStored procedures using the standard libraryORM frameworks or librariesIndividually these have both pros and cons, often leading to heated debate and discussion.InlineLeaky abstractions.Dangerous in places via SQL injection.Quick and dirty solution.Non testable by default.Useful for integration testing where dynamic input is required and safe.Stored Procedures (standard library)Can be clunky and low level to use in places.Non testable by default.Allows the use of DB specific features internally.Easy to tune and optimize as long as interface is stable.Developers can optimise the execution of queries.ORMsTestable by default.Complex, large and difficult to use correctly.Leaky abstractions.Optimisation is harder, especially for DB engineers.Mini or lightweight alternatives exist, with less of the downsides.Polyglot PersistenceThe actual decision of which data access m…

Getting Things Done - For Software Developers

I have been using the incredibly simple techniques within Getting Things Done (GTD) to good effect over the last twelve months.The SystemAt a high level the system consists of buckets, grouping and a task store. The actual implementation of GTD systems is down to personal preference. Many find their system changes and evolves over time.BucketsHave one or more buckets which act as simple dumping grounds for anything you need to do. My phone, pen and paper and post it notes are the three core buckets I use.Buckets are where you store anything that takes more than a couple of minutes to do. If something takes less time, just do it there and then. Regularly empty the buckets and assign them to groupings of related items. Example groupings include tasks around the house, work projects, blog items, or items to buy.GroupingEach grouping can then be allocated a priority. Each grouping essentially becomes a mini kanban board.Grouping is preferred to having one big todo list as different scenar…