1. 程式人生 > >Using Vectors & Boxes to scale Design Thinking

Using Vectors & Boxes to scale Design Thinking

Using Vectors & Boxes to scale Design Thinking

“Quality” is a mis-represented term in engineering. Let’s fix the context here to growing startups, early in their journey. Prioritisation, sprints, workflow management between teams is all very shaky and bootstrapped.

I have often heard people talk about the following to identify and solve for quality — code reviews, granular metrics for errors and response time, documentation, software tools to gauge code base committed, unit test coverage, etc.

However, most of these only solve half the problem. Extra time for quality is a luxury for startups. Metrics help gauge breakage (assuming errors and logs have been well structured), but having a bug-free code doesn’t mean good code quality. Code reviews work well but are often ineffective when the reviewer is fragmented across projects and is mostly doing syntax / style reviews. Code reviews are also often too late in the the dev cycle to change code architecture. Documentation is tough to get right because it requires constant upkeep. Unit tests and coverage proactively tests breakage but not the design.

What is the most important aspect of “quality” in a young company then?

Coding is art. Modularity at the right place, in line with the future business goals, is key.

Quality is best defined by how easy or hard is it to extend on top of an already written code block.

But this can’t be gauged easily. Hence, the way to better this design-thinking is by figuring out good frameworks of thinking that could be spread across the team. If done well, every engineer is left a lot more empowered to own his doing in a way that scales for the team.

Introducing Concepts, Vectors & Boxes.

At UrbanClap, to have people start thinking a lot more of design, we enforced “Design Reviews” with a certain way of hosting them. Before a project started, engineers had to submit a Concept / Box / Vector version of what they were doing. This “modelling” exercise forced them to think of the design, the dependencies, the interfaces. A structured framework also helped save a lot of brainstorming time.

Design Reviews – How-To-Do-Them-Right.

The two big areas to discuss are –

  1. Outside Architecture (Concepts , Boxes , Vectors)
  2. Inside Architecture (Folder structure, Code blocks)

Outside Architecture.

Example – Best explained with an example to support. An at-home service request (Request) often requires product items (Item/s) to be consumed (eg – cosmetics, spare parts). This inventory is pre-purchased (Order) by professionals (Provider) from UrbanClap. UrbanClap enables this by buying these products from 3rd party vendors to help consolidate and standardise this inventory in it’s warehouses, and facilitate the ordering and tracking of these orders . UrbanClap also has fraud-detection systems to detect if the inventory used on the job matches their purchase pattern, and correct fraudulent behaviour by sending out communication and levying penalties. Let’s demystify this using the techniques below.

Concepts. Define all the data required as concepts / nouns. These concepts form the dictionary of all the data used, nothing outside these should be used to reference. Eg – Request, Item, Order, Provider, etc. End goal – create the vocabulary.

Here are the concepts from the example.

Boxes. Given you have your vocabulary set with the Concepts, now comes the phase to brainstorm and draft what components need to be built and how they all interconnect. Start with dividing your feature/system into single-purpose boxes. Use only boxes and nouns to draw out all the components. Go as granular as you can. Do not have nested boxes. Each box should serve only one type of purpose, else it needs more division. Create a full picture by chalking out the downstream services (i.e. where you are getting the data from) and upstream services (i.e. who might be querying the new code). Idea is to quickly divide your thoughts into independent pieces at a high level without filling out details. Remember, single-purpose boxes. End goal – create a modular map of your system.

This is a brainstorming exercise to arrive at the full box-picture. It started with step 1, and got divided into boxes till a full, crisp map of components became clear in step 4.

Vectors. With the vocabulary set and a rough thought on the modularity, its time to define what each component does. Take each new “box”, and try defining it’s purpose using ONLY the “concept” vocabulary.i.e. Vectors & Functions. Each box could be modelled either as a data-repository or as a function with input / output. This is their primary purpose. You could further chalk out the different APIs that would be needed to give a fuller picture. At a design phase, best done by annotating the different kinds of APIs exposed without jumping into details (CRUD, Aggregator, Search, Computation). End goal – crisply define the purpose and contour of each component.

Good design exercises and reviews require mathematical art work. If done well, should be enough to give shape to what needs to be done, and what the contours are.

This makes for an effective way to objectively communicate without using too many spoken words. This ensures a quick way to think modular design. This ensures you have thought deeply about modularity. This ensures you have well defined components and their contours. This ensures you have thought through the downstream dependencies and the upstream use-case.

Inside Architecture.

For those more OCD about quality, you might want to go a step deeper in how the code inside the modules will look like. Instead of waiting for the code to be written, or to have long discussions around implementation, here is a quick way to structure it.

Folder Structure. Write down the whole folder structure before you start. The modularity of your actual code is represented with the folder / file structure you have. Sibling folders / files can access each other, but not inside the other. Enforcing the proper access of code at a folder/file (modules) level wins you most of the battle w.r.t. modularity.

Example –
/service_name         /index.js                --- to contain the interface         /service_name.service.js --- to contain the implementation

Code Blocks. Before starting to write, pseudo-write code-blocks and functions. Discuss this and get this reviewed. Each code block should be independent in its purpose. Do not write code. Simply mark functions, and code blocks within them with a simple line stating what will happen.

Example of code-blocks

You will realise, a majority of your time is getting spent in modelling components, chalking dependencies, and structuring code. Once this is done, filling in the extra details is a piece of cake. Minimal code foul. Maximum big picture thinking.

A few more things.

A few more details to seek when perfecting design –

  1. Dealing with Legacy (data , migration and legacy code)
  2. Flavour of Data Access / Storage (batch, bulk, sync, async)
  3. Monitoring Strategy
  4. Testing Strategy

Aftermath.

What happens as a result of scaling this framework is that code automatically starts to decouple and engineers start to care a lot more about the “usefulness” of their design. Less time is spent on communicating what. Multiple teams (including product/design) start to talk in terms of boxes and vectors/functions. This eventually map to and makes it easy to split teams. With a well modularised code base mapped to a well mapped team, it becomes easy to define and track granular metrics. Due to the proactive work on quality, less time is spent on refactors and maintenance and more time is spent on problem solving and impact . …. …….. you get the eventual picture.

In conclusion, as fast paced engineering teams, the biggest problem which is often hidden from the naked eye is that of “design”. Solving well for that in the initial days goes a long way.

“Good Design” is not just an engineering concept. It shapes how a company internally “thinks”. You know you have made good progress in design when product-engineering interactions go from contractual documentation about features and flows, to, building capabilities via boxes and vector math.