mobile it

 

 

Development rules for better productivityhttps://mobileit.cz/Blog/Pages/development_rules_for_better_productivity.aspxDevelopment rules for better productivity<p>​Each project has its own rules for development. Most often, these rules describe development practices and work with a version control system (VCS) that outlines how to test and deploy the product, the structure, the architecture of the project, and the code style, but the rules can also include the basics of secure development and more.</p><p>These rules can be unwritten but are usually defined and recorded in a shared space where everyone has access to them. Yet more important is how these rules are applied and enforced in practice.</p><h2>Wise men know it best</h2><p>Some people believe that pair programming or code review is an appropriate platform for rules revision. Participants can agree on the application of the rules or change them based on context. When developers approach this conscientiously, the result can be a project that may not be consistent, but its individual parts will be in the best possible shape.</p><p>This approach may lead to better results for a short period of time at the start of a project, but its shortcomings will start to become apparent over time. Even experienced developers and technical leads are just people. They can occasionally get tired or simply overlook something. Thus, minor deviations from the agreed-upon rules pile up and begin to form so-called technical debt.</p><h2>Time trial</h2><p>The next aspect that reflects in time is the expansion of the project, and this is on two levels.</p><p>The first is the expansion of the product itself. As the product becomes successful, it receives new and more sophisticated features that begin to connect previously simpler and independent features. This is where the small deviations and inconsistencies that at first seemed good for the functionality start to show up. The problem is that now more of these functions need to be compatible with each other, but they are not ready for it.</p><p>This is not just a problem of incompatibility of features. Often, well-intentioned developers try to reuse existing components as much as possible to avoid code duplication. They forget the rule that we can reuse a component when we expect the same behavior but also have the same reasons to change. If this condition is not met, the Single Responsibility Principle is violated and the project has low flexibility for future development.</p><p>The second level of project expansion is the development team itself. Once the product becomes successful, sooner or later it leads to the expansion of the development team. The new team members do not know the whole genesis of the project and thus do not have the same understanding of the rules as the older members who set the rules themselves. This leads to misunderstandings and yet another minor deviation from the agreed rules, which again increases the technical debt. A side effect is an increased need for communication during pair programming and code review, which reduces the overall productivity of the team.</p><p>These problems in project expansion are not limited to large development teams, but also happen to smaller ones. For example, when a two-person team introduces two new developers, the productivity of the team may hardly change. And all this is due to the circumstances described above. Without knowing the cause of the problem, it can lead to further blind "strengthening" of the team and make it even worse.</p><h2>Tripping comes before a fall</h2><p>When a development team repeatedly fails to finish agreed features or is unable to release a new version of a product for technical reasons, one of the critical scenarios occurs. At this point, people outside the standard development team get involved in discovering the cause and solving the problem. Together, they all work under stress and with a lot of human effort to get the development back under control. It is only at this point that a retrospective analysis takes place to uncover the true causes of the problems.</p><p>Yet the accompanying symptoms and spring of these problems have been manifesting themselves for a long time in advance. A few subtle situations as examples: </p><ul><li>A developer repeatedly receives feedback on misnaming during code review.</li><li>A ticket in the project issue tracker does not contain a reference to the implementation due to a typo in the project source code. </li><li>A feature that is still under development is enabled in the test version of the application.</li></ul><p></p><p>Often they just look like minor ambiguities, individual mistakes, or accidents that sometimes happen during development. When these situations recur, their negative impact on team productivity and the project's error rate quickly increases. But if we look closely at them, we can see blank spaces in the way we work that are actually easy to fill and solve the problem once and for all.</p><h2>Live rules</h2><p>To avoid the problems mentioned above, we need to have clearly specified development rules. Their content should reflect the individual needs of each project. For some projects, it will be critical to clearly define collaboration with the QA team and describe the release management of the product, while other teams will focus more on collaboration between developers within the development itself.</p><p>The more detailed and specific the rules are, the better their effect on the team's work will be. Therefore, it is not possible to start from a general template, but each team must define these rules themselves.</p><p>Sometimes we see cases where a team defines a few basic rules of a more general nature at the start of a project but does not develop them over time. Thus, the rules never accurately represent how the team works, and even the little they contain becomes meaningless over time.</p><p>Nothing is set in stone, and even an established team changes the tools it uses or discovers new ways of working over time. All these natural changes have an impact on the team rules. They remain alive and valid.</p><h2>Automate everything</h2><p>In the introduction, we briefly discussed the form the rules can take and the possible ways of applying them. To be most effective, rules must be applied automatically without the need for manual control. Likewise, we must think about the productivity of the team, which can be reduced by the influence of a large number of repressive rules. Therefore, tools that help team members automate certain steps are an integral part of this process. These tools save time and their output is naturally in line with the defined rules.</p><p>In practice, it is so common that Code Style or Project Architecture is enforced by automated rules, but at the same time, there are code templates and formatting tools that do most of the work for the developers without them being aware of it.</p><p>Most issue tracking tools provide a programmatic interface so that it is easy to automate the creation of a new development branch in VCS so that the new code is linked to a specific issue. Similarly, it is possible to create a VCS hook that checks that a corresponding issue exists for a given branch or commit for cases when the developer has created the new development branch manually.</p><p>Release management is a completely separate chapter. When releasing a new version of a product, there are generally routine and clearly defined steps that need to be performed. Here, automation not only gives us the assurance that the release of a new version will be done in an orderly and error-free manner but it also speeds up the process and allows for easy knowledge sharing between team members. A bonus is an easy automation of generating release notes, even if only for internal testers.</p><p>Testers will also appreciate the ability to configure the product for internal testing. They can toggle a feature flag, configure the environment the application runs against, or have the ability to simulate scenarios that are difficult to do manually. Besides the undeniable benefit of these test tools for testers, it has benefits for the developers themselves. They don't have to maintain more versions of the product than strictly necessary, which saves them time by fundamentally simplifying the build logic.</p><p>This is just a small sample of the rules we commonly encounter on projects. However, it is far from exhaustive of the options, whether they are related to quantity, depth, or sophistication.</p><h2>How far to go?</h2><p>Some rules may seem strict enough to restrict your freedom to work. Others may seem so vague that they will not have the desired effect. That's all right. Every team and every member has different needs and different perceptions of risk. All of this has a bearing on the form of the rules.</p><p>In our projects, we try to define the rules strictly by default. Over time, when we find that they limit us too much, it's easy to make the rule more generalized or turn it into a recommendation or warning. The opposite approach is considerably more complicated, because the team and its operation have already become accustomed to the more general rule, so it may not be possible to make a change overnight.</p><h2>Project sustainability</h2><p>When developing a product, in addition to the short-term goals of making the necessary features, we always consider the idea of long-term sustainability and viability of the project. Especially in mobile development, it is not an exception to the opinion that a project should be discarded once every 2-3 years and developed completely from scratch. This is a real disaster in terms of productivity.</p><p>In our portfolio, we have apps that are more than 7 years old and have gone through several major changes during their lifetime. On a business level, there has been a change in targeting a different sector of users and aligned with changes in branding and design. On a technical level I would mention the switch from Java programming language to Kotlin, or the transition of asynchronous work from a custom imperative solution to a reactive approach via RxJava and later Kotlin Coroutines. Even so, the development team is still only two people (while they are altering throughout) and at the same pace, it delivers new functionalities according to the business needs.</p><p>Clearly defined development rules and the consistency enforced by them have a major impact on the quality of the final product in every way.</p><p>Next time we will take a closer look at how some rules can be implemented and what tools we have for this.</p><p><br></p><p>Pavel Švéda<br></p><p>Twitter: <a href="https://twitter.com/xsveda">@xsveda</a><br><br></p>​<br>#productivity;#team-collaboration;#architecture;#automation
Our Minimalistic Approach to 1st and 2nd Level Supporthttps://mobileit.cz/Blog/Pages/Our-Minimalistic-Approach-to-1st-and-2nd-Level-Support.aspxOur Minimalistic Approach to 1st and 2nd Level Support<p>​At one of our projects, we're working in a scrum team counting around 10 people. The product has gradually been rolled out to more users and is getting traction. This is good because it provides us with a tangible metric of our product's reach and it gives us more opportunities to validate our ideas in the real world as we see how users react to them.</p><p>Some of the users are also proactively providing feedback about things that are cumbersome, hard to use, or outright buggy. So far we (with a major contribution from our product owner) have managed to gather and process the feedback in an organic way. </p><p>Over time this activity has grown to a considerable effort and has started to consume precious time and we've started to feel like things are slipping through. We need to find a more robust way to handle the user requests.</p><p>The goals we want to achieve by having a link to the users are far from unique. To name a few:</p><ol><li>Collect defect/incident reports</li><li>Collect feature requests</li><li>Help users with troubleshooting</li><li>Have a feeling for the general user's sentiment</li><li>Respond to and inform users</li></ol><p>We don't want to have just a <q>passive</q> way of collaboration with users (meaning only to collect input) but we'd like to be able to respond in a relevant way to their reports or questions. We want them to know what they can expect from us and likewise let them know they're heard and that their contribution is welcome.</p><p>Unsurprisingly, we discovered the majority of users' requests were repeats of the same thing. Users either did not understand a certain feature or a general expectation was misaligned with the product itself.</p><p>Many of the user issues could be resolved quite easily by answering directly and potentially providing further explanation if needed. It became obvious that we need to focus on improving UX here and there. Or bring a new feature because users are repeatedly struggling with certain actions.</p><p>But in order to draw useful conclusions from the numerous inputs and to convert them into prioritized backlog items, we needed more <q>human processing power</q> and a way to somehow standardize the inputs.</p><p>This led us to introduce a combination of a few new concepts.</p><h2>Introduction of bug reports</h2><p>We implemented a bug report function. We wanted to keep it as simple for the user as possible. So after clicking the <em>report bug</em> icon the only thing the user needs to write is an answer to the question <q>What did you expect to happen?</q> and to click a confirmation button.</p><p>We attach a lot of metadata to this and the bug report is then visible in our product's back-office web. This alleviates the need to read through emails and keeps the form uniform to some degree. It also automatically collects crash logs.</p><p>So far we have decided not to integrate this to JIRA for a reason I will explain in a minute.</p><h2>Introduction of support levels</h2><p>The customer for whom we are building the product is a large corporation and one of their business activities is software services. That means they have a department full of people experienced in 1<sup>st</sup> level support activities. So it appeared as a logical option to collaborate with them on this as it was preferred to use in-house personnel.</p><p>This idea posed a few challenges nonetheless:</p><ol><li>How to define competencies?</li><li>How to bring them to a level of knowledge necessary for stand-alone work?</li><li>How to help them with unexpected things?</li><li>Find a way to report problems they can't resolve on their own.</li><li>How to keep them up-to-date with the latest fixes and features?</li></ol><p>We decided to follow the 3-level support model. In our development process it meant the following:</p><h2>1<sup>st</sup> level: </h2><p>Roughly 4 people from the help desk department were selected to join us part-time. Their competence within our development process is:</p><ul><li>Answering general users' questions.</li><li>Resolving user issues that don't require a change of system data or the system itself.</li><li>Passing unresolvable issues to 2<sup>nd</sup> level support.</li><li>Collecting data about frequent bugs.</li><li>Bringing ideas to mitigate the most frequent user complaints/questions.</li></ul><h2>2<sup>nd</sup> level: </h2><p>For the time being, we have decided to bring one extra person who will tackle this alongside our product owner. </p><ul><li>Resolving incidents stemming from bad system data via our system's back-office web.</li><li>Resolving issues that 1<sup>st</sup> level support lacks knowledge of.</li><li>Adding new articles to the knowledge base for the 1<sup>st</sup> level support</li><li>Passing issues to 3<sup>rd</sup> level support</li></ul><h2>3<sup>rd</sup> level: </h2><p>This is the actual scrum team. So the job is to prioritize and implement what comes through the support pipeline.</p><h2>Setting up new flows</h2><p>In order to keep the new 1<sup>st</sup> and 2<sup>nd</sup> level support colleagues in the loop we invited them to our asynchronous communication channels. This way we could quite flexibly answer their questions without the need for yet another regular meeting and it seems it helped their learning process. As of now, they are already quite knowledgeable and their questions are getting more and more <q>advanced</q>. We feared the number of questions could overwhelm us, but it seems we managed it and the ad-hoc communication is effective.</p><p>We also invited all of them to the sprint review meetings, so that they are aware of the current situation and know when the bugs reported by them are done. This is also a perfect place for them to express any general observations and opinions about how they perceive priorities of items reported by them compared to other backlog items.</p><p>For the most frequently occurring questions or problems, we created a simple knowledge base that the 1<sup>st</sup> level colleagues can use while troubleshooting user issues. 2<sup>nd</sup> or 3<sup>rd</sup> level support people occasionally add new articles if a question gets repeated.</p><p>We've been using JIRA as a tool for keeping our backlog since the beginning of the project. Our fear was that introduction of formalized support levels could bring large overhead, so we decided to keep the tools as simple as possible. We don't need any sophisticated helpdesk system. </p><p>Therefore we decided to create two new issue types in JIRA and right in our project space. We called them (no surprise here) a <em>1<sup>st</sup> level ticket</em> and a <em>2<sup>nd</sup> level ticket.</em> Those tickets got a very basic state flow: <em>Open ​→​ In progress →​ Closed + 2 more: Waiting for a reply and Reply obtained</em>.</p><p>We decided to use the original JIRA project space for the 3 support levels. The main reason was to let everyone inspect the backlog if necessary and to check how things are progressing. The second reason was to avoid complexity in our flows.</p><p>By doing this, 1<sup>st</sup> and 2<sup>nd</sup> level support people can also comment on any existing issue in the backlog in case they have relevant additional information. In order to keep things organized we simply created a few new quick filters to view <em>only the 1<sup>st</sup> level tickets</em>, the <em>2<sup>nd</sup> level tickets</em>, or to <em>hide them</em> and view the backlog just as it was before the 1<sup>st</sup> and 2<sup>nd</sup> level people joined in.</p><p>Both of the new issue types also received a button to conveniently convert the issue to a <q>higher</q> one. Meaning that from <em>1<sup>st</sup> level ticket</em> we create a <em>2<sup>nd</sup> level ticket</em> with a click of a button. And from the <em>2<sup>nd</sup> level ticket</em>, we create a <em>bug</em>​ or a <em>user story</em> in the same way. In addition, we created two new boards to display just the respective issues type and their current states.</p><h2>Time will tell</h2><p>So far this model has worked well for us. We get a feeling of safety knowing there is no negative sentiment accumulating among the users we wouldn't know about and could explode later. The test of time will tell if we need to modify the process. Many more users are expected to start using the product. As with anything in such an environment, we will certainly need to adapt eventually. We just don't yet know when. I will come back with an update after we're wiser again.</p>​<br>#agile;#project-management;#scrum
Scope and Time Fixationhttps://mobileit.cz/Blog/Pages/scope-and-time-fixation.aspxScope and Time Fixation<p>​When planning for a milestone such as a release or a development finish, there are several approaches we can choose from. A traditional (and often intuitively chosen) approach is to try to predict and fix all the project imperatives. What does this mean?</p><p>As a countermeasure to reduce the number of unexpected events at the beginning of the project, it is common to make a detailed plan months in advance and expect the development teams to keep it. </p><p>Let's say we want to do a major release of our software. The product owner and the stakeholders make their expectations about a release date, the content (scope) it’s going to include, and the cost. In the best case scenario, their expectation is based upon a discussion with the development team.</p><p>The development proceeds and the release milestone approaches. More often than not, the team encounters unpredicted problems and some of the features are delayed. As the release date approaches, it becomes clear that the release plan is endangered. The team starts to get anxious. Then, shortly before the release date, it is evident that not all of the planned scope is going to be finished. As a result, the date gets postponed by managers with the hope that the remaining scope will be finished on time.</p><p>Moreover, additional requirements from the stakeholders arrive and the product owner wants to include them in the release to gain positive perception. The release has already been postponed once, so it would be great to overperform this time. As it usually happens in development, fresh bug reports arrive. Let's include corresponding fixes in the release too. A vicious cycle begins.</p><p>The point is that the more a release keeps getting postponed, the higher is the temptation to include additional content to make up for previous disappointment. Usually, a release is postponed multiple times and gets delivered weeks or months later with a great deal of nervousness.</p><p>What helped our teams in such situations?</p><h2>Back to the basics</h2><p>The first thing we hear when you learn about project management approaches, is how the combination of time, cost, and scope work together. The traditional approach is that in the planning phase of a project, it is decided what functions we will create, how much it will cost, and how long it will take. As I covered in my <a href="/Blog/Pages/scrum-smells-7.aspx">previous posts</a>, I believe it is a futile effort to attempt to make an exact determination of <em>all of the three project imperatives at once</em> as reality rarely follows them in the long run.</p><p>When we define a fixed scope, fixed timeline, and fixed cost, there is virtually no room for flexibility if something goes wrong. From my observations, the effect is usually that in the (probable) case of unexpected problems, it is the quality of the delivered scope that gets sacrificed. In other words, it is an attempt to make the scope somehow flexible by re-interpreting its definition.</p><p>This usually leads to the project manager trying to negotiate a later time for a handover (or release). There is a tendency to check off as many items of the scope list as possible, so that it looks good in reports and on paper the project can proceed to the next phase (and possibly allowing for a payment milestone). But under the hood, shortcuts were taken and oftentimes the pressure to <em>deliver something</em> comes at the cost of the software being defective and half-functional. </p><p>In scrum terminology the scope items are not done. There is a technical and/or business debt. Contrary to the definition of done, there is still known work to be done on these items.</p><p>The costs for paying off the debt are considerably higher than the effort necessary in getting it right at the first go. In many cases, it also means that <em>nothing</em> can be released due to numerous defects. The whole package remains unacceptable. </p><p>Agile approaches try to keep one of the three imperatives (scope, time and costs) flexible. We have a given team with a certain development capacity. That team consumes a predictable budget over a given period of time. What options do we have?</p><ul><li>Team capacity (staffing): affects the throughput over time. Changing it influences the rate at which budget gets consumed and scope gets developed. In this article I assume that the team is naturally using its resources effectively and attempts to improve its performance over time as it matures.</li><li>Development duration (time): affects how much scope can be delivered with a given capacity and lets us cap the invested budget.</li><li>Scope: changing scope will affect how long a given team consumes the budget.</li></ul><p>So if we have a specific budget we need to invest, we can set a suitable team, calculate how long the budget will last, and keep the scope flexible. Or the other way around, if we want a precise scope to be developed, the timeline becomes the bumper. Also, the team size needs to be chosen adequately. We need to be able to supply it with high value business requirements meeting the definition of ready.</p><h2>How to combine time and scope</h2><p>Unless we are in a very rare case when the product aspects are well predictable (process-like activities), we must accept the fact that we need to prioritize the project imperatives. In my experience trying to juggle both scope and time at once usually leads to a lot of confusion and it often sabotages any rhythm the team may have. I believe prioritizing one over the other is the way to go.</p><p>On our projects we usually keep the team capacity at a reasonable level and then prioritize time over scope. That means we set a particular milestone in the calendar and concentrate the activities into making it happen. The scope is the flexible element. </p><p>Let's use an example. The product owner wants to make a release of an update on the market. He deems that it’s worth doing it a month from now because that will bring a considerable improvement to the user and will create a positive perception.</p><p>The product owner and the team make their preliminary prediction about what backlog items they expect to deliver. The team spends that month working on them. As usual, they discover considerable complications with some backlog items along the way and major defects are also reported from the users. Then it becomes clear that not all of the originally expected backlog items will get done by the release date.</p><p>The development team, together with the product owner re-prioritize the backlog to incorporate these new findings. It is decided that the resolution of certain bugs would bring considerable value. Problematic backlog items are put off, so that the team does not spend effort on something that will probably not be finished. The team focuses on the sole goal of making the product releasable at the given time. They are not obsessed with the necessity of delivering absolutely <em>everything</em> that they originally thought. Functionality that will not be included in this release will be contained in the successive one.</p><p>Figuratively speaking we need to draw a horizontal line in the backlog. There are two options for where to draw it. It's position is either fixed and the exact development duration will be adjusted, or time is set and the position of the line in the backlog can be adjusted along the way - it floats.</p><p>By keeping the backlog constantly refined, well prioritized, and the backlog items as atomic as possible, we are maximizing the chance that what falls over the line isn't vital.</p><p>In the example above we used a release as a milestone. But a milestone can be any other critical event - such as consumption of the project's allocated budget.</p><h2>It sounds easy, but...</h2><p>This idea is nothing revolutionary. But putting it into practice usually includes avoiding a few frequent mistakes:</p><ul><li>Avoid stakeholders from expecting strict time and scope fixation. It takes effort to explain that there always needs to be an approach to minimize risk of critical stuff falling over</li><li>Avoid stakeholders from putting you into a situation where <em>everything is equally important</em>. It is the job of the product owner (with the help of the scrum master) to educate them about this.</li><li>Don't be tempted to postpone the release milestone just a little so that you can fit in that one extra valuable item. It's better to set a regular schedule for releases and be safe in the knowledge that it won't take long before the next release.</li><li>Don't juggle with both scope and timeline at once. Prioritize one over the other.</li><li>Don't cling onto past predictions. The situation always evolves and rather constantly evaluates if the prediction is still valid or not.</li><li>Don't get caught up in details. Use the dailies to take a step back and see how the team is progressing towards a goal and if there are any new obstacles in the path.</li></ul><p>Psychology plays a major role when things don't follow the budget - scope - time triangle. But it would be naive not to proactively take steps for when it happens. Deciding on a general strategy - whether to fix time or scope - takes a lot of weight off the team's shoulders and makes development much more predictable and manageable. So always think about what can be sacrificed from the original predictions if things go wrong.</p><br>#agile;#project-management;#release-management;#scrum
Marginal Utility and Product Managementhttps://mobileit.cz/Blog/Pages/marginal-utility.aspxMarginal Utility and Product Management<p>​​​​​​Today I'd like to browse into the waters of economics. There are certain concepts that I believe are highly relevant to the way we build software products. You might be wondering, how do these two fields come together, but bear with me, they are more connected than we often realize. Understanding some basic ideas of behavioral economics can help us steer software projects as it provides us with a different perspective on the prioritization and value-maximization process, which I write about frequently.</p><h2>Utility</h2><p>Before we get to the marginal utility we need to understand some basic concepts. What is a utility anyway? It is an economic term that refers to how much satisfaction a person will get from consuming a particular good or service. The important part to understand is it's the total utility one gets from consumption of certain goods. This is given by the sum of satisfaction one gets from consuming all the individual parts of it.</p><p>​Let's look at an example. Assume you are eating a pizza. The total utility you get from that pizza is how much satisfaction it provides for your particular needs when eating all the single slices. In this case the need you satisfy is typically just hunger (need to eat and/or cravings).</p><p>How can we measure utility? Unfortunately, most of the time it is not directly possible. You can't objectively measure how much satisfaction eating a pizza can bring. On top of that it is highly individual. The satisfaction (utility) you get from eating pizza will probably differ greatly from the satisfaction that the same pizza will bring to Bob, who is allergic to gluten and ate lunch a few minutes ago.</p><p>But what we can do is to compare the value that different goods or services can bring to you. In a given moment you can compare the utility of a pizza compared to that of a steak. The one you'd rather eat is the one with the higher utility to you. You can also compare it to the satisfaction a particular water would bring. Or a car. Or a house. You can assign some abstract dimensionless value to each of the potential goods (similar as we do it with story points) and those can be compared.</p><p>It is obvious that utility, even for a single individual, varies greatly depending on the context. You might say a house would be of a much higher value than a bottle of water. But would you still insist on this if you were parched and lost somewhere in a desert? The famous line <em> <q>My kingdom for a horse</q></em> is a good demonstration of this phenomenon.</p><p>Utility is context dependent and that is also why people are willing to pay different money for the same good when the situation changes. Buying used skis is usually going to cost you less in summer than in winter because people don't demand them as much. Trying to sell ice cream on a beach in summer is an easier job than doing the same in winter time. Context matters for utility.</p><h2>Marginal utility</h2><p>Knowing that, what is a marginal utility? This concept measures how much utility will the next unit of a good or service bring. The total utility is then the sum of all marginal utilities you get from individual parts of that good or service.</p><p>Back to that pizza. Eating a first slice will give you much satisfaction because you went from starving to having something to eat. That was the marginal utility of the first slice.</p><p>The second slice will probably be almost equally satisfying because you are still hungry. But will the 8th slice be as satisfying? Probably not because your hunger is gone by the time you get to it. So gradually we usually tend to get lower and lower marginal satisfaction of each additional unit of a particular good we consume.</p><p>An interesting fact is that marginal utility can also be negative. How much satisfaction would eating the 24th slice of pizza bring you? It would likely not be something you would voluntarily eat (unless you're attending some who-eats-the-most-pizza contest). That one extra slice of pizza could make you sick and therefore cause a negative experience. The marginal utility of the 24th slice would be negative and the total utility of the whole meal would start getting lower.</p><h2>How does all this connect with software development?</h2><p>We're building a software product that serves people. Their motivation to use it stems from the fact that they get some satisfaction out of it. Their needs get fulfilled when something that was once difficult gets easier thanks to our product.</p><p>When building a software product, we have limited resources to fulfill those needs. So we all know we should maximize the value of the time (or other resources) we invest into building it. That is no surprise.</p><p>How can the economical concept help us? I have seen a natural tendency by the product owner (and the rest of the development team including the stakeholders) to attempt to define backlog items as the final form of a software feature; a form that immediately brings users the <em> <q>fullest</q></em> and most <em> <q>perfect</q></em> possible behavior.</p><p>I won't go into deeper detail here, but if you are interested please check one of my <a href="/Blog/Pages/product-development.aspx">previous posts</a> on this topic .</p><p>Understanding the marginal utility concept can help us overcome that psychological barrier of not wanting to reduce individual backlog items to atoms. We want to bake the whole pizza with prosciutto and mozzarella on top of it, serve it with water and wine on a table with a nice view of the sunset because that is what we imagine the product is supposed to look like eventually.</p><p>But let's view it from a different perspective. Why do users want our software product? If we use the pizza analogy, what is the <em>first slice of pizza</em> that we can give them? The slice that will not make users feel fulfilled yet and at the same time cause them to not die of hunger anymore. We can apply the same approach to the whole product backlog preparation and simplification of the individual items.</p><p>Frequently a user story as it is written solves multiple users' needs at once without us realizing it. Remember the email example from the post I mentioned above? A typical user story could say that when you view an email, it gets marked as read, it gets rich-text formatted, embedded images get displayed etc. That is how you would imagine such a feature to ultimately behave.</p><p>What happens, when we apply the marginal utility concept to that story? What is the <em>first slice of pizza</em> that we can develop and decide about the rest later? What aspect of that story has the highest <em>marginal utility</em> for the user? Most likely the ability to actually read the text in that email. The <em>marginal utility</em> of being able to read the content is typically greater than the one of rich-text formatting, image display, or marking messages as read. Suddenly it becomes obvious that the story can be broken down into more atomic slices.</p><p>By asking this question over and over again usually helps to make up the mind as to how worthwhile it is to invest effort into something. It also makes negotiations with stakeholders easier because it somewhat materializes the cost/benefit concept.</p><h2>Know the users</h2><p>As stated before, utility is highly individual and context-dependent. That is why the user stories start with <em> <q>As Bob the truck driver, I'd like to have...</q></em>. A software feature for one person will likely have a totally different value (utility) compared to another. That is the reason it is vital to know well who we are building the product for. To know their real-life problems.</p><p>Only then can we evaluate the marginal utility of our product's features relevantly <em>for them</em>. The capability to view images embedded into emails is going to give wildly different satisfaction to a clerk receiving simple instructions in the text compared to a gallery owner wanting to receive previews of paintings from artists.</p><p>When we know the audience we can reasonably decide how we can split backlog items into more atomic ones and identify what <em>the next slice of pizza</em> should be. That's also why getting real-world feedback as early as possible is so crucial for relevant decision-making. Describing utility highly contextual to a particular person is the reason why <em>user</em> stories are called <em>user</em> stories in the first place.</p><h2>Final words</h2><p>Managing the backlog well is a difficult job. We need to keep it meaningfully prepared, juggle with the item's values, compare the costs and returns. That's why it's good to take a chance and look at the same thing from a perspective by applying some basic economic concepts to it. I hope this sparked some inspiration for your own development process.</p> <br>#agile;#development;#project-management;#scrum
The Last Scrum Guide Updatehttps://mobileit.cz/Blog/Pages/2020-scrum-guide-update.aspxThe Last Scrum Guide Update<p>​​The updated scrum guide has been out for more than a year, so many have already written about it. But I would like to take this opportunity to share a few thoughts about the scrum guide as such and also comment on some of the features in the latest update. </p><h2>Is scrum guide underrated?</h2><p>The scrum guide is in my experience often overlooked by teams or organizations. I dare to believe I might know some of the reasons. When I was first learning about scrum and I was trying to live by it with my colleagues, we needed a lot of guidance. We needed a hands-on approach by our more agile-seasoned colleagues to actually help us set the basics and actually start working in the framework. We needed to discuss the nitty-gritty details of the daily work and all the various aspects of backlog management. We sought after organizational how-tos and best practices to wrap our heads around this interesting, yet somehow elusive concept of scrum. </p><p>Scrum is easy to understand but difficult to master. It is mainly a cultural shift compared to traditional project management and development approaches, so why is it so hard to get right? Sometimes the actual cultural shift is the culprit, but it is also demanding for organizational and planning discipline. </p><p>The actual nuts and bolts are often what teams struggle with and that's where they seek a lot of help in the earlier phases of their maturing. The scrum guide however does not give many answers in this regard. And that's why a lot of people don't find much practical use in reading that document. It seems to me it is rarely a go-to place for teams or scrum masters when searching for scrum answers.</p><p>But the scrum guide was never meant to be a detailed guide. And that is a good thing. Its purpose is to set the boundaries just where they are absolutely necessary, outline the philosophy, and leave the space for interpretation where the scrum team is supposed to bring in its brains and creativity. It tries to be as precise as possible without being taxative. And for this very reason, it needs to be minimalistic. (If only our legislators approached their work this way…)</p><p>In my opinion, the more the team matures, the less it should try to seek exact how-tos about living in scrum, but the more it should return to the bare basics - to the scrum guide.</p><p>That helps to gain some distance from the daily routines and undesired habits and look at their doing from the above to get rid of unnecessary habits and rather focus on the actual philosophical value than a process. Matured teams have a pretty good idea about the philosophy of scrum and want to live by it. Going back to the guide can be an enlightening experience for them. Approach the scrum guide as it's been triple distilled before it got its current shape.</p><h2>Recent updates</h2><p>At the end of 2020, the scrum guide received yet another update. Although some of the changes seem minor or sound just like a wording change, to me it seems like a good step towards helping to clear up several common misconceptions. You can find the changelog easily on the internet, so it is not my aim to cover the update extensively. I want to talk about a few particular changes, which I find the most interesting.</p><h3>1. Ditched the 3 questions for dailies</h3><p>Everyone knows the 3 questions that are the core of the daily - what did I do, what will I do, and do I have any impediments, right? So the guide got rid of them. Why is it a good thing? Because the ultimate team's purpose of the daily is to evaluate sprint backlog's achievability and to make decisions upon this evaluation. Decisions to make the team create the most value within the sprint (and to still meet the sprint goal). Maybe by dropping some sprint backlog items. Maybe by re-assigning backlog items between the developers. Maybe by helping each other out. </p><p>These questions were sometimes obscuring the actual goal of the daily. As if it was forbidden to talk about anything else other than that. Does it mean that these 3 questions should not be used from now on? No, it doesn't. It certainly is necessary that the devs share their progress and sync on it. If the team finds them useful, it will use them. The guide just suggests that these questions are not the pivotal point of the daily and give more freedom to the team to tailor the daily to their needs.</p><h3>2.Stressing the core scrum values and principles</h3><p>The guide now tries to be clearer about the core scrum values and principles of empiricism. It reminds us that being transparent, inspecting, and adapting based on the findings is a vital part of the process. This is as opposed to extensive planning and attempting to achieve perfection for the first time.</p><p>Commitment, openness, and respect are the values that shape the actual outcome. The often-used practices like estimating, tracing velocities, and plotting burn-downs are icing on the cake. But the team should be able to bring high value even without them.</p><h3>3. Team unification</h3><p>Formerly, scrum the guide defined a developer team and a scrum team. Scrum team = development team + scrum master + product owner. From now on, there is just a scrum team. </p><p>To me this is not just a cosmetic change. Sometimes the teams gained a dynamic of the product owner being an outsider. A customer for the team. Subliminally perceived as a competitor or a hindrance to the development team. In some teams, even the scrum master was seen as an outsider.</p><p>Team unification is an attempt to get rid of the us-and-them mentality. When perceived right, all the team members have a common goal to solve problems to create high business value. And the devs can (and should) be in close touch with the product owner to work out how to keep achieving that continuously. It needs to be clear that to the developers, the product owner is not an enemy, but someone who they can use to get answers, opinions, and business insights from, to be efficient. They can negotiate with him about the possible approaches to solving particular problems. When there is a good idea to achieve something in a more efficient or simpler way than originally intended, devs should understand that both them and the product owner will benefit from it. And the product owner should understand that too. They are teammates.</p><h3>4. Commitments for scrum artifacts</h3><p>The hierarchy of artifacts and their commitments is now clearer. A product has its goal. That determines the product backlog's priority. A sprint has a goal, which defines the sprint backlog. And finally, a product increment must meet a definition of done. This is nothing really revolutionary or entirely new, but more clearly formulated, something that most people intuitively already sensed and used.</p><p>In general I see this update as an evolution rather than a revolution. Or better said - another cycle of distillation. Cheers!</p> <br>#scrum;#agile;#project-management
SwiftUI and Architecture: Statehttps://mobileit.cz/Blog/Pages/swift-ui-and-architecture-state.aspxSwiftUI and Architecture: State<p>A new era has come to the mobile world. At least in the context of UI frameworks. What does this mean for your project? Will your architecture stand strong and allow for incremental adoption? Or will you have to resort to complete rewrite?</p> <h2>​​Welcome to the new old world</h2><p>The cornerstone of user interface development for iOS since its inception has been UIKit (or AppKit for macOS). It provides a mechanism to define window and view hierarchy, navigate between scenes, render content on the screen, and has tools for handling user interaction. UIKit was designed over a decade ago in the Objective-C world and leverages principles that were common back then, like delegates and inheritance. Functional elements of modern languages like Swift naturally lead to a declarative programming paradigm which is where SwiftUI steps in.</p><p>The SwiftUI framework was announced at WWDC 2019 and introduces the aforementioned declarative approach to writing UI code, favors composition, uses value types extensively and provides under the hood optimization. It completely changes how we reason about the UI and how we write the UI code. Its principles and design are inspired by React from the Javascript world, which dates back to 2013, so our thanks and a round of applause are in order for the JS community for working out its kinks!</p><p>Code written in SwiftUI is multiplatform and can be deployed to tvOS, macOS, and watchOS platforms. Interoperability with UIKit and AppKit helps with the transition even further.</p><p>Interestingly, a very similar approach also came to the Android world, known as Jetpack Compose. If you are more interested in this, it is well described in posts "Jetpack Compose: What you need to know", <a href="/Blog/Pages/compose-1.aspx"> <ins>part 1</ins> </a> and <a href="/Blog/Pages/compose-2.aspx"> <ins>part 2</ins> </a>, although since then some things inevitably changed. </p><p>Both of these technologies are ready for production use. Let's focus on what the arrival of SwiftUI means from the architectural point of view, especially regarding state.</p><h2>SwiftUI and state</h2><p>In SwiftUI, a view is a function of a state, not of a sequence of events changing some internal, encapsulated state. What does that mean in practice?</p><p>SwiftUI observes UI state and triggers re-rendering of the view on every change (with some smart optimizations happening under the hood). This is done by property wrappers that annotate UI state objects and/or Combine publishers. It's only up to you to model, hold, transform, compose and distribute the state.</p><p>The state can be perceived from many different angles, for example:</p><ul><li>what is rendered on the screen,</li><li>data that are persisted in the storage,</li><li>state that's spread across multiple screens or features.</li></ul><p>It is crucial to properly separate these kinds of states from each other, as some have a limited role in a merely encapsulated context, while others may span across multiple contexts and may serve the purpose of the source of truth.</p><p>Such a source of truth must be unambiguously defined and shared. Let's take a look at how the currently most discussed architectures approach this.</p><p> <strong>MVx architectures</strong></p><p>MVC was most commonly used in iOS applications back in the day. It got sidetracked with the advent of functional reactive programming and was replaced with MVVM and its derivative MVVM-C which specifies an additional layer for navigation. The place for View and Presentation logic is clear in those cases, but the Model layer has too many responsibilities, which might lead to big components that have too many concerns. In another case, the Model layer may contain only domain objects whereas the Presentation layer deals with networking, storage, business logic, and transformation of domain objects into renderable objects for the view on one side together with handling actions from the view on the other side. Huge ViewControllers with many responsibilities led to the joke saying MVC is short for Massive-View-Controller.</p><p>MVx architectures are not sufficient by their definition to design the whole system. They are merely a pattern for the presentation part of the system. Clean and robust applications may be written with MVVM as the only architecture tool in your toolbox but it requires strict discipline and proper decomposition. The architecture used often branches out into something more sophisticated than 3-layer architecture but with no clear boundaries that are defined somewhere between the lines.</p><p> <strong>Redux</strong></p><p>As the SwiftUI is inspired by React from the Javascript world, where React and Redux often go hand in hand, it's natural to think about how this is mirrored in mobile application development.</p><p>Redux is a mechanism to update and distribute state around. It cannot be considered as "architecture" as it does not answer the important questions</p><ul><li>how to protect the app from the outside world?</li><li>how to enable easy change of technologies and third-party dependencies?</li><li>how to define strict boundaries to isolate features?</li><li>where are the business rules defined?</li><li>which parts deal with navigation, presentation, networking, storage, user input, and so on?</li></ul><p>These discussed architectures do not address modeling and state sharing in complete detail, they are often either used in a poor way that is not very readable and sustainable, or in a way that inherently leads to a more complex architecture with a looser definition of responsibilities.</p><p>Although SwiftUI is a new player on the mobile playground, managing state is definitely not. Let's see if the old and traditional principles still have anything to offer in this new world.</p><h2>Lessons learned from history</h2><p>There are many patterns and principles that are timeless, namely two that enable to store and distribute state in a transparent way.</p><p> <strong>Repository pattern</strong></p><p>A repository is a design pattern that abstracts data access logic from business access logic by exposing the collection-like interface to access business entities. The actual implementation of the interface might communicate with the database, REST API, and what your project requires as long as it doesn't leak its details to the business domain interface.</p><p>Such a repository could easily be the source of the truth for each feature. Repositories obviously hold the state, but let's see how to distribute the same state to multiple parts of the application.</p><p> <strong>Dependency Injection</strong></p><p>Sharing state across features is as simple as sharing the same repository instance. Dependency injection frameworks help organize the dependency graph. Some use Service Locator patterns that abstracts instance resolution behind an abstraction layer. It reduces boilerplate code you would otherwise need with manual dependency injection. The resolution might cause runtime crashes if some requested instances are not registered. That's a downside that can you can handle with unit tests though.</p><p>You can also implement a shared repository using pure language without any dependency frameworks. The principle remains the same in both cases.</p><h2>Architecture and state</h2><p>It's important to design your system</p><ul><li>to be soft and malleable, so you're able to swiftly deliver changes that are desired,</li><li>but robust enough, so that you can be sure those changes are not going to cause unexpected behavior, </li><li>and clear enough so it's easy to navigate and doesn't grow over your head.</li></ul><p>Decoupling is critical to achieving that. To decouple views, view models, scenes, and what have you, you need to figure out how to share the source of truth across the app. If you mishandle it or don't think much about the state, you're going to have a hard time even with UIKit applications as it leads to coupling that results in code that's hard to test, read and reason about, for instance:</p> <img alt="MVVM" src="/Blog/PublishingImages/Articles/swift-ui-and-state-02.png" data-themekey="#" /> <p>ViewModels in this case do way too much. They pass state among each other which makes them difficult to test and harder to read. The source of truth for these data is also lost, it's unclear where the state originated and who owns it.</p><p>State management is not something new that came with SwiftUI, it's been here for decades, and there are no specific new architecture requirements. If you make features independent, inject your dependencies, test, and define the source of truth with a repository pattern, you can design your system to be easier to maintain and grow, regardless of which UI framework you pick.</p> <img alt="Clean Architecture" src="/Blog/PublishingImages/Articles/swift-ui-and-state-01.png" data-themekey="#" /> <p>There's a strict boundary between features in this example. ViewModels only transform data and actions between Views and UseCases. There is one clear source of truth for each feature. Isolation leads to reusability and testability.</p><p>State management was always important in app development, unfortunately often it was neglected or done poorly. Declarative UI concepts do not bring anything new to the table as they just explicitly accent what's important to handle well because the view is a function of a state.</p><h2>Old and new, together</h2><p>Breakthrough technologies such as SwiftUI don't come out that often, but that doesn't mean that your app and architecture should succumb to being completely dependent on the technology and/or derive itself from it. On the contrary, if you adhere to the separation of concerns and decouple your code, you achieve strictly defined boundaries and can start adopting those technologies without having to rewrite most of your app and even do so incrementally.</p><p>SwiftUI is a brand new technology, but that doesn't mean we can't benefit from timeless and classic principles that helped deal with many challenges over many decades. Old and new can go hand in hand together and complement each other to enable us to create brilliant apps.</p>​<br>#swiftui;#architecture;#state
Scrum smells, pt. 8: Scrum has too many meetingshttps://mobileit.cz/Blog/Pages/scrum-smells-8.aspxScrum smells, pt. 8: Scrum has too many meetings<p>Countless times I've heard from developers that scrum makes them waste time by assigning too many meetings. I've heard that from people who have used scrum, or shall I say people who have attempted scrum adoption.</p><p>So let's get this straight today. Why do developers often feel there's too much talking and too little <em>real work</em>? Is that really what scrum is supposed to address?</p><h2>What does the scrum guide say?</h2><p>Let's have a look at the scrum guide. It says that the following events should take place:</p><ul><li>Daily scrum (maximum 15 mins per day)</li><li>Sprint planning (maximum 8 hrs per month)</li><li>Sprint review (maximum 4 hrs per month)</li><li>Sprint retrospective (maximum 3 hrs per month)</li></ul><p>On top of that, the guide tells us to perform backlog refinement, but it does not specify a particular meeting or event for it. Scrum guide says to allocate approximately 10% of the time for refinement activities. That makes for 4 hrs a week or 12 hrs a month.</p><p>So it all adds up to one whole work-day being occupied by <em>not working</em>, right?</p><h2>Developer role perception</h2><p>New scrum adopters usually come from a world where software developers are a narrowly defined role. Such developers get a requirement from a business analyst and documentation from a solution architect. They get UI components from a designer. They take it, do their coding part, and hand the stuff over to someone else to integrate and test it. The responsibility for preparation, planning, and verification is not their responsibility and out of their competence.</p><p>The Agile approach believes this is not very efficient. It strives to create small development teams where everyone is a developer, contributing to the creative process from the thinking phase up to the verification and deployment. This development team has much more deciding power, can choose its own strategy and course of action, and (in the ideal world) the stakeholders rely on its honest judgments.</p><p>That's what makes it more effective. A group of experts communicating with each other will usually come up with better ideas and solutions than a single person. So the team has the freedom to choose their way when tackling a problem. But in order to do that the team also needs to have the means to understand the problem fully. It needs space to coordinate effectively and choose a course of action and necessary tools. It also needs to make sure they work on meaningful things.</p><h2>The blind flight</h2><p>We intuitively feel that some sort of the so-called <em>overhead</em> is necessary so that the team can figure out what it needs in order to work effectively. Without any communication or preparation, efficiency could hardly ever be achieved.</p><p>And that is essentially why scrum prescribes the events it does. The sole purpose is to facilitate the team's ability to work effectively on relevant and valuable items. It is the imperative that gives meaning to all the single events that happen within the team. It's not a bunch of random separate meetings. It's a concept.</p><p>One of the principles of Agile development is to constantly remove activities that are not useful. So let's try to apply this to the key <em>overhead</em> activities that happen within scrum. Let's view the ceremonies without their labels for a moment. What would happen if we removed:</p><ol><li>Operative team synchronization. The on-the-go chance for the team to synchronize on its progress, make short-term plans and decisions. Removing team synchronization altogether would create a bunch of individuals working alongside each other, not a team. Such individuals would not adapt and help each other out to achieve a common goal. Removing such activity would destroy effectiveness. </li><li>Making a plan - both, a long and short-term one. A chance to look a few weeks or months ahead and to decide what to work on. To prepare a strategy on how to distribute the work, realize what to beware of, and get some distance from daily work. Removing planning activities would cause an inability to work on relevant stuff, to use the team's resources effectively, and foremost any ability to see the context of what the team is working on. A releasable product increment at the end of the sprint would become a coincidence, not an intentional act. Development becomes a blind flight.</li><li>Improving the way the group works. A review of what works and is useful and what are the painful points. Any system that lacks a self-feedback loop can't improve and adapt to changes. Removing attempts to change the way of work prevents any improvement from happening, which leads (among other things) to a drop in team member motivation and involvement. </li><li>Keeping the stakeholders in the loop. Not only do we need to gather feedback if we're on the right path. But more importantly, we need to manage the expectations of people around the team to keep them aligned with reality. The more these expectations drift away, the more troublesome the whole environment becomes. Angry people who have the power to influence the project in a negative way are the last thing we need.</li><li>Deciding on what to actually do. Preparing the backlog into a state, where developers know they can actually deliver it. And that it is worthwhile doing. Dropping such activity leads to a situation, where we invest efforts into irrelevant things.</li></ol><h2>Where is the culprit?</h2><p>We see that the activities above are all necessary to have a working project or product development. They need to happen, somewhere, sometime, invisibly, organically along the way. They always happen, regardless of what we call the project or product management approach. It's just that the scrum guide tries to concentrate them into an organized scheme so that it is easy to follow. It makes it visible. So why not use the concept and rather reinvent the wheel?</p><p>From my experience, the distaste for scrum events usually stems from the team not fully understanding the implications of omitting some of the five key overhead activities I mentioned above. Especially the role of refinement activities is often completely misunderstood and the implications of letting the backlog rot are not sufficiently feared. I wrote on this <a href="/Blog/Pages/scrum-smells-4.aspx">topic previously</a>.</p><p>In addition, a narrow perception of a developer's competencies and responsibilities is another key factor. The mind shift required to view people as an active element in the product design, planning, and decision making usually takes some time. The goal is to finish stuff as a team, not to be just a cog in a machine which does not have any power to change things. And to achieve that, the activities of a developer must not be limited just to coding.</p><p>Thirdly, an ineffective way of leading scrum events. The ceremony is held just because the team is supposed to hold it. The meeting should be done, but no one actually has a clue as to why they gathered and what the purpose of the meeting is. It has no clear guidance, no clear gist. Meetings serve just for a single person (often a product owner or a scrum master) to communicate direction to the developers. The developers feel that they don't have the power to change things anyway - that the organizer is just trying to make an illusion they have the freedom to decide things, but in the end, someone else's decision is superior. That makes the developers feel cheated. It genuinely feels like a waste of time.</p><h2>The way out</h2><p>From my experience, the process of fully understanding and appreciating scrum activities (and the ceremonies supporting them) comes with the team's maturity and guidance. If led well, the team will sooner or later learn from the painful implications of omitting them. </p><p>It would, however, be a mistake to enforce a particular <em>correct</em> way of doing them. I find it is usually better to offer experience and practices that have worked for other teams, but let the team find their own taste for how to perform it.</p><p>The development team is a self-organized unit that has the right (and obligation) to decide on the best way to solve problems. Let's take it also into the exact form of how the scrum events are held. If there's something to be made otherwise to foster the effectiveness and the goal of the meeting itself - why not do it? </p><p>Let the team give them space to learn from it. That is, I believe, the best way to keep teams running and becoming effective in the long run. Agile principles are empirically oriented after all.</p>#scrum;#agile;#project-management;#release-management
Building a chatbot, pt. 3: How to design a conversationhttps://mobileit.cz/Blog/Pages/chatbot-3.aspxBuilding a chatbot, pt. 3: How to design a conversation<p>As users, we require a good and practical interface when interacting with any system. It has to be simple enough for us not to get lost in it. At the same time, it has to meet all the needs we might have. The same applies to interactions with a chatbot. The conversation has to be simple enough so the user is not bothered with unnecessary information. On the other hand, it has to cover all possibilities that might occur when processing a user's request. </p><p>In previous articles, I described our chatbot solution that uses checklists as the main element of conversation design. In this article, I would like to share our process of creating a complex conversation from a simple feature request. </p><p>Since the design is specific to our chatbot solution, I will use the same tools for design as we use during real development, that is, pen and paper. Surprisingly, these are still the best tools to use. As a design template, I will use finite state machine diagrams. This is to simplify analysis and also it serves as a template to use in the final code implementation. So what will be shown? Circles and arrows. Every circle represents one piece of information that is successfully processed by the bot. Every arrow represents an input sentence or a condition that is imposed on data already provided during the conversation. </p><h2>Feature request</h2><p>Let's say that we have the following request for a chatbot feature from a customer:</p><p><em>In our company, we have meeting rooms that we use daily. We need to schedule our daily calls and business events like product demonstrations and virtual meetings. We need you to create and design a conversation feature that will enable us to book a room. Also, let's send an email to all colleagues that need to attend a given meeting. It would be nice if we could append an optional message. If any of the colleagues already have another meeting set up, then the organizer needs to see this information beforehand.</em></p><p>To simplify this example, we are going to assume that all other layers necessary for this feature are already prepared (sending emails, checking the schedule of users, etc.). That way we can focus solely on the conversation design.</p><h2>Simple conversation line</h2><p>Let’s start our first conversation design by looking at this:</p><p><em>In our company, we have meeting rooms that we use daily. We need to schedule our daily calls and business events such as product demonstrations and virtual meetings.</em></p><p>So how can we approach this? As designers and analysts, we have to think from the perspective of the chatbot. What information do we need to achieve the goal of this request? We will need to know at least the time of the meeting. There should be an action specification, and to avoid other interpretations we should ask the user for a clarification of the object, a room, in this case. From this we can put together our first checklist:</p><ul><li>Book</li><li>Room</li><li>Time or time range</li></ul><p>Once we have all this information we should be able to move to the next step. In this case, the bot will make a reservation and send an email. Now let's transform this checklist into the conversation diagram:</p> <img alt="simple conversation" src="/Blog/PublishingImages/Articles/chatbot-3-01.png" data-themekey="#" /> <p>We will have 4 steps in conversation. In each step there will be an interaction with the user if this conversation was not specified earlier:</p><ol start="1"><li>What would you like to do? -> <em>Book</em></li><li>What would you like to book? -> <em>Room</em></li><li>When would you like to plan your meeting? -> <em>Tomorrow from 9:00 to 11:00</em></li><li>I have created a reservation for you</li></ol><p>Congratulations. We have designed our first conversation. What will happen if a user creates a single line with all specifications like this?</p><p><em>Book me a room for tomorrow from 9:00 to 11:00</em></p><p>In our chatbot solution, we only ask for information that we don't have. In this sentence all the information is present and so the only response from the bot will be number 4:</p><p><em>I have created a reservation for you</em></p><h2>Optional parameter</h2><p>Now let's have a look at the next part of the feature.</p><p><em>We need you to create and design a conversation feature that will enable us to book a room. Also, let's send an email to all colleagues that need to attend a given meeting. It would be nice if we could append an optional message.</em></p><p>For now, let's focus on the <em>optional message</em> specification and deal with <em>adding users</em> later in this article. </p><p>From the previous iteration our checklist looks like this:</p><ul><li>Book</li><li>Room</li><li>Time or time range</li></ul><p>After time specification we should give the user an option to add a message to his email. A simple question should be enough. How about:</p><p><em>Do you want to add a custom message for your colleagues?</em></p><p>If the answer is yes, then we ask the user for the message itself. Otherwise, we move on to the reservation. We need to enhance our previous design a bit:</p><ul><li>Book</li><li>Room</li><li>Time or time range</li><li>Do you want to add a custom message for your colleagues?</li><ul><li>Yes - add a message</li><li>No - no message</li></ul></ul><p>At this point we have multiple possibilities on how to convert this checklist into a diagram. User interaction should be always the same but as we know, there are multiple ways to design a system. This is one of the possible approaches:</p> <img alt="optional parameter" src="/Blog/PublishingImages/Articles/chatbot-3-02.png" data-themekey="#" /> <p>We’ve added a few steps to the previous diagram. The first 3 are the same. At the fourth one, we will ask for additional users, but for now, we can assume that this is taken care of, and we can focus on step 5. We can assume that the conversation from the chatbot point of view can be prepared like this:</p><ol start="5"><li>Would you like to add a custom message for your colleagues?</li><ol type="a" start="a"><li><em>Yes</em> - Ok, what would you like to say?</li><li><em>No</em> - Alright (and continue with I have created a reservation for you)</li><li><em>“users message”</em> - Great, I will make sure your colleagues get this. (and go back to step 6)</li></ol><li>I have created a reservation for you and your colleagues.</li></ol><p>There is a reason for designing a conversation in this way. This conversation branch can be reused. We can use the same branch when adjusting this meeting. Or in another conversation where we need a custom message.</p><p>Now let’s see what the conversation for this iteration can look like:</p><p> <strong style="color:#381457;">User</strong> : <em>Book me a room for tomorrow from 9:00 to 11:00</em><br> <strong style="color:#9d9d9d;">Bot</strong> : <em>Would you like to add some of your colleagues?</em><br> <strong style="color:#381457;">User</strong> : <em>Yes, add Michael and Jordan</em><br> <strong style="color:#9d9d9d;">Bot</strong> : <em>Alright. Would you like to add a custom message for your colleagues?</em><br> <strong style="color:#381457;">User</strong> : <em>Yes</em><br> <strong style="color:#9d9d9d;">Bot</strong> : <em>Ok, what would you like to say?</em><br> <strong style="color:#381457;">User</strong> : <em>Prepare your ideas for teambuilding!</em><br> <strong style="color:#9d9d9d;">Bot</strong> : <em>Great, I will make sure your colleagues get this. I have created a reservation for you and your colleagues</em><br> </p><h2>Complex enhancement and iteration</h2><p>In the last part of our design, we should introduce a way to add multiple other users to the meeting. Let's have a look at the relevant part of the request:</p><p><em>Also, let's send an email to all colleagues that need to attend a given meeting. It would be nice if we could append an optional message. If any of the colleagues already have another meeting set up, then the organizer needs to see this information beforehand.</em></p><p>Again we find ourselves at a point where there are multiple possible approaches to design a conversation that would satisfy this request.</p><p>I will present one of the possible approaches. The checklist for it will look like this:</p><ol start="1"><li>What would you like to do?</li><li>What would you like to book?</li><li>When would you like to plan your meeting?</li><li>Would you like to add your colleagues to this meeting? Who is it going to be? (<em>list of users</em> / <em>no</em>)</li><ol type="a" start="a"><li>Great that makes “N” of your colleagues, would you like to add more users? (<em>yes</em> / <em>no</em>)</li><li><em>Yes</em> - Alright, who’s next?</li><li><em>No</em> - Alright</li><li>Consider it done. (and back to point a) - Great that makes “N” of you...</li><li><u>Some of the users are already occupied</u> - I am sorry, but this / these user(s) already has / have another meeting scheduled. Would you like to create a meeting without them or invite them anyway? (<em>remove them</em> /<em>invite them anyway</em>)</li><li>Ok, that means {list of users} will participate</li><li>Alright, I will send an invitation to all the users you’ve listed</li><li><u>The current user is not present in the listed users</u> - Are you going to participate as well? (<em>yes</em> /<em>no</em>)</li><li>Ok, I will add you to the list of participants</li><li>Alright</li></ol><li>Would you like to add a custom message for your colleagues? (already done)</li><li>I have created a reservation for you</li></ol><p>So what does this checklist tell us? We start with a straight question - if there are going to be additional users. If not, then we direct the user to another part of the conversation - a custom message. For an affirmative answer (list of users should be also considered as an affirmative answer) we will move into additional questions. Here we can iterate and ask the user if the list of his colleagues is final. If so, there should be some validations and quality of life questions. Those can consist of checking given users if they are in our system. Or we can ask the user if he also wants to participate if his name is not already on the list. Also, this is the place for checking other users’ schedules for conflict meetings. Once everything is sorted out and the user is able to navigate all the possibilities, we should wrap this part of the conversation and move into a custom message part. And that part is already sorted out, so we should be done with the design.</p><p>Now let’s have a look at the diagram of this approach. For simplicity, it only shows the part for adding users.</p> <img alt="Complex enhancement and iteration" src="/Blog/PublishingImages/Articles/chatbot-3-03.png" data-themekey="#" /> <p>From a simple and straight conversation, we’ve arrived at a really complex conversation full of questions from the bot and required answers from the user. But every possibility is covered and the user will have a list of all participants eventually. The first part (steps <em>a</em>, <em>b</em>, and <em>c</em>) deals with adding users. Then we process both conditions for conflicting meetings and current user participation. After that, we return a final list of users back to step 4 and we are done.</p><p>Even though this design is quite elaborate, the user conversation should be natural:</p><p> <strong style="color:#381457;">User</strong> : <em>Book me a room for tomorrow from 9:00 to 11:00</em><br> <strong style="color:#9d9d9d;">Bot</strong> : <em>Would you like to add some of your colleagues?</em><br> <strong style="color:#381457;">User</strong> : <em>Yes, add Michael and Jordan</em><br> <strong style="color:#9d9d9d;">Bot</strong> : <em>Great, that makes 2 of your colleagues, would you like to add someone else?</em><br> <strong style="color:#381457;">User</strong> : <em>Yes</em><br> <strong style="color:#9d9d9d;">Bot</strong> : <em>Alright, who’s next?</em><br> <strong style="color:#381457;">User</strong> : <em>Alfred and Molly</em><br> <strong style="color:#9d9d9d;">Bot</strong> : <em>Consider it done. Great, that makes 4 of your colleagues, would you like to add someone else?</em><br> <strong style="color:#381457;">User</strong> : <em>No</em><br> <strong style="color:#9d9d9d;">Bot</strong> : <em>I am sorry, but Jordan and Molly already have another meeting scheduled at this time. Would you like to create a meeting without them or invite them anyway?</em><br> <strong style="color:#381457;">User</strong> : <em>Invite them anyway</em><br> <strong style="color:#9d9d9d;">Bot</strong> : <em>Ok. Are you going to participate as well?</em><br> <strong style="color:#381457;">User</strong> : <em>Yes.</em><br> <strong style="color:#9d9d9d;">Bot</strong> : <em>Ok, I will add you to the list of participants. Would you like to add a custom message for your colleagues?</em><br> <strong style="color:#381457;">User</strong> : <em>Yes, please.</em><br> <strong style="color:#9d9d9d;">Bot</strong> : <em>Ok, what would you like to say?</em><br> <strong style="color:#381457;">User</strong> : <em>Prepare your ideas for teambuilding!</em><br> <strong style="color:#9d9d9d;">Bot</strong> : <em>Great, I will make sure your colleagues get this. I have created a reservation for you and your colleagues</em><br> </p><h2>Conclusion</h2><p>From a feature request to a solution - that should be a goal of every application developer. We took this vision and applied it to a chatbot solution. In essence, almost any issue that can be solved by a conversation with a person should be possible to convert into a conversation with a chatbot that will handle it as well, no matter the complexity, no matter the subject. There are still cases that we are not able to fit into an automated conversation, but that is another topic.</p><p>From a simple conversation to a complex one, there is always a way for a design that can give users the ability to finalize their task. For the best user experience, we should mind their requests and adjustments.</p> #chatbot;#ai;#neural-network
So you want to create a design system, pt. 4: Layouts & dimensionshttps://mobileit.cz/Blog/Pages/design-system-4.aspxSo you want to create a design system, pt. 4: Layouts & dimensions<p>People today can choose between an incredible number of mobile devices that vary enormously in display size and resolution. How can you ensure your app looks and handles great on all of them? Let’s talk about dimensions, positions, and layouts, and how they fit into design systems!</p><h2>Absolute nonsense</h2><p>Some very popular design tools do this:</p> <img alt="Sample mobile screen with hardcoded dimensions" src="/Blog/PublishingImages/Articles/design-system-4-01.png" data-themekey="#" /> <p>It all looks nice and thoroughly specified, doesn't it? Wrong! Dimensions specified in absolute values have long been unusable for several reasons:</p><ul><li>Mobile device displays vary widely in terms of physical pixels.</li><li>Mobile devices also vary widely in terms of absolute physical display size—many phones are now approaching 7 inches, while at the other end of the spectrum devices around 5 inches are more than common. </li><li>The aspect ratios of displays also vary widely—today we can commonly see ratios such as 16:9, 18:9, 18.5:9, 19:9, 19.5:19, 20:9, 21:9, and this is by no means a complete list. </li><li>Since the advent of retina-like displays, physical pixels have become more or less irrelevant, and instead, we have to consider units independent of actual display density. </li><li>The amount of space your application gets on the display for rendering itself may vary depending on the presence, position, and size of system bars or display cutouts. </li><li>The operating system may also feature some sort of split-screen mode; and don’t get me started about foldables, large screen devices, and the like. </li></ul> <img alt="Different screen aspect ratios" src="/Blog/PublishingImages/Articles/design-system-4-02.png" data-themekey="#" /> <p>When designing screens for mobile devices, this means that you know literally <em>nothing</em> about the display, making absolute dimensions totally pointless (this also applies to platforms with a limited number of well-known models such as iOS—who knows what displays iPhones will have next year?). Hopefully, design tools will start to take this into account, but until that happens, we need to help ourselves in other ways.</p><h2>Units united</h2><p>So if physical pixels are no longer usable as a unit of dimension, what to use instead? Well, each platform has its own way of specifying dimensions independent of physical resolution, and unfortunately, you have to account for all of them in your design system.</p><p>For example, Android uses two units: scalable pixels (SP) for text sizes and density-independent pixels (DP) for everything else (actually, even that isn’t entirely true—as far as raster bitmaps are concerned, good old pixels are sometimes used as well, and Android letter-spacing units are totally weird). Moreover, SPs and DPs are converted to the same physical size by default, but this need not be the case if the user so chooses (for accessibility purposes).</p><p>Confused? This is perfectly understandable, but if the design system is to be usable, there is no choice but to learn how each platform handles dimensions, and then use those ways everywhere in the specs. The second best option is to use some abstract universal units and provide a conversion formula for each platform, but this way is more error-prone than specifying platform-native units that developers can use directly.</p><h2>Get into position</h2><p>Even when using platform-specific units, absolute positioning is still not feasible. So how do you adapt your layouts to all possible screen configurations?</p><p>The answer is relative and responsive positioning. Two things need to be specified for each component: Its dimensions and its relative position to some other component, its container, or screen. Together, these parameters form constraints that are used to unambiguously and responsively specify the entire layout, regardless of screen size, aspect ratio, etc.</p><p>Size constraints can be specified as:</p><ul><li>wrapping or “hugging” the content of the component</li><li>occupying all (or a proportion) of the available space</li><li>fixed values, but only in specific cases (e.g. icons)</li></ul><p>Some components may have additional options. For example, a component for displaying text can limit its height to the maximum number of lines displayed, or a component for displaying images can have a fixed aspect ratio.</p><p>It might be useful to add auxiliary parameters to these constraints, such as enforcing minimum or maximum dimensions, but then you must take care to prevent conflicts with other constraints.</p><p>The constraints for width and height are independent and can freely combine the above options, but only so that the resulting size is always unambiguous.</p><p>Relative positioning is quite simple: Each component must be anchored somehow in both horizontal and vertical directions to:</p><ul><li>another component</li><li>the container in which it is placed</li><li>the screen (this option must be handled with care)</li></ul> <img alt="Components and constraints" src="/Blog/PublishingImages/Articles/design-system-4-03.png" data-themekey="#" /> <p>Since the application has no control over how large a display will be available (and what its aspect ratio will be), nor how large the dynamic content will be (e.g. image size or text length), it is always necessary to specify a strategy for what to do if all the content does not fit. The basic options are:</p><ul><li>to make the component scrollable (remember that there is also a horizontal direction, but horizontal scrolling is usually much less intuitive) </li><li>limit the text by the number of characters or lines—in this case, it is necessary to also specify the indication of overflow (ellipsis, some kind of fade effect...) </li><li>crop the image to a fixed dimension or predefined aspect ratio (including the specification of whether to stretch or fit the image into the resulting container) </li></ul><h2>Everything’s not relative</h2><p>While the dimensions and positions of components should be specified as relative where possible for the design to be responsive, there are still situations where we need to use absolute values:</p><ul><li>spacings between components (or their margins)</li><li>container paddings</li><li>corner radii</li><li>dividers</li><li>elevation and/or z-index (depending on your platform, these may or may not be two different things) </li><li>small spacings used to visually align the parts encapsulated inside reusable components (e.g., space between icon and text inside a button) </li><li>parts of the typography specification (e.g., line-height; although in some cases these can be specified relatively as well) </li></ul><p>For the first five cases, it is absolutely essential (as in the case of <a href="/Blog/Pages/design-system-2.aspx">colours</a>) to introduce semantic dimension constants into the design system and then use them exclusively in all designs. You don't want to hardcode these values because it's easy to make a mistake when using them, and you also want to use them according to their purpose, not their value (which means there's no harm in having multiple semantic constants resolved to the same size).</p><p>So how to name these semantic constants? The first part is simple—it should always express the primary purpose (<span class="pre-inline">spacing</span>, <span class="pre-inline">padding</span>, <span class="pre-inline">cornerRadius</span>, <span class="pre-inline">elevation</span>, etc.), possibly combined with secondary usage (e.g., <span class="pre-inline">padding.screen</span>, <span class="pre-inline">padding.dialog</span>, etc.). In some cases, you’ll also need several size variations for a given purpose, so it's good to have a system for naming these variations as well, for example:</p><ul><li>size adjectives like <span class="pre-inline">tiny</span>, <span class="pre-inline">small</span>, <span class="pre-inline">normal</span>, <span class="pre-inline">medium</span>, <span class="pre-inline">large</span>, <span class="pre-inline">huge</span>—these work well, but don’t go overboard with quirky names like <span class="pre-inline">tiniest</span>, <span class="pre-inline">reallyReallyLarge</span>, <span class="pre-inline">humongous</span>; you need to be sure that the order from smallest to largest is always absolutely clear </li><li>T-shirt sizes like XS, S, M, L, XL, XXL—their order is unambiguous, but if you find out later that you need another value between, say, L and XL, you'll have a problem (this also applies to the first option to a certain degree) </li><li>clearly (this is important) dimensionless numbers without semantics like 100, 150, 200, 400, 1200—have the advantage of allowing you any number of values, you can always squeeze a new one between any two, and their order is unambiguous, but a problem will occur if this number is confused with the actual value, which is why I would recommend this only as a last resort (needless to say, the name of a constant must never contain its value) </li></ul><p>Putting it all together, your design system can define set of dimensions such as</p><pre> <code class="kotlin hljs">dimension.padding.screen.normal dimension.padding.screen.large dimension.padding.dialog.normal dimension.spacing.small dimension.spacing.normal dimension.spacing.large dimension.spacing.huge dimension.cornerRadius.normal dimension.cornerRadius.large dimension.elevation.none dimension.elevation.normal </code></pre><p>What actual values should these constants take? This is where it's also good to have a system so that your UI has a consistent rhythm. Different platforms usually have a grid defined as a multiple of some value (e.g., on Android it is 8 DP), and it's good to stick to that (so for example <span class="pre-inline">dimension.spacing.normal</span> might be 16 DP, <span class="pre-inline">dimension.spacing.large</span> 24 DP and so on) because your app always shares the screen with at least a part of the system UI, and ignoring the default grid might make your app feel subconsciously “wrong”.</p><p>And finally, what about the last two bullet points—dimensions used to visually tweak space inside encapsulated components, or in text styles? In this case (and only in this case!) I dare to say: hardcode them. Yes, I know, after all the talk about semantic constants, isolating values in one place and all that, this is unexpected, but I have two good reasons for that: </p><ol><li>These dimensions are implementation details of isolated, otherwise totally encapsulated components or text styles. They are completely hidden, not used externally anywhere, and not reused nor reusable. </li><li>Especially in the case of smaller components, these values are completely arbitrary, chosen based on visual appeal, and don't have to follow a predefined grid at all (e.g., if your button looks best with vertical padding of 3 DP, just use that value). </li></ol><h2>Putting it all together</h2><p>So let's apply the techniques we mentioned above to the example in the first figure:</p> <img alt="Sample mobile screens with dimension properties" src="/Blog/PublishingImages/Articles/design-system-4-04.png" data-themekey="#" /> <p>This is much better! Systematic and responsive, a UI specified this way is much easier to implement and use.</p><p>There are other things to think about:</p><ul><li>With interactive elements like buttons, the platform's minimum tap target size <em>in both dimensions</em> must be respected at all times. This includes not-so-obvious things like hyperlinks in paragraphs of text and the like. </li><li>If your app is running in fullscreen mode, you need to be <em>very</em> aware of and careful about display cutouts, the system UI overlaying your app, etc. </li><li>Modern phones are getting bigger and bigger, and if you use such a device single-handedly, you can't reach the whole screen with your fingers anymore. In this case, the screen is effectively divided into several zones, which differ substantially in how well they can be interacted with. Moreover, often the place that is the most prominent when visually scanning the screen (the top left corner) is also the hardest to reach physically, and vice versa. You have to take this very much into account and design a suitable compromise. And don’t forget about left-handed people! <img alt="Regions on phone screens reachable with a thumb" src="/Blog/PublishingImages/Articles/design-system-4-05.png" data-themekey="#" /> </li><li>Gesture implementation is another can of worms that we won't go into here. Even if your app doesn't support any custom gestures, current mobile platforms use system gestures that can interfere with your app. </li><li>Another major topic (for another blog post maybe) is support for foldable and large displays. This is where things like breakpoints, multi-panel screens, and the like come into play, and it's a whole different ballgame. </li></ul><h2>Design your system, systemize your designs</h2><p>This concludes our series on design systems. I hope it has helped to make the design and implementation of your mobile apps more consistent, easier, and more efficient, and who knows, maybe even a little more fun.</p>#design-system;#ui;#ux;#development;#android;#iOS