shopping for quality

Shopping for Quality- How to Ensure You're Hiring a Company That Can Deliver

Written By: Lawrence Waugh, Founder at Calavista


I’ve written before that most people who are looking for a software development firm to deliver code for them tend to really care about 3 things. Those things are:

1) Price
2) Quality
3) Speed of delivery

There’s no surprise there – those are the things we all care a lot about in most purchases. No one wants to overpay, buy inferior goods, or wait interminably (or maybe indefinitely) for most anything they buy. I’ve written previously about ways to minimize cost (spoiler alert: Fixed Fee is not your friend). In this post, I want to focus on quality.

How can you be sure the company you engage will deliver high-quality code at whatever price you’re paying them?

The good news is that it’s easier to tell than you may think.

Don't believe the hype

The first thing to realize is that any company can say anything they want about themselves. It doesn’t matter how nice their website looks – that’s the work of the marketing group and has nothing to do with how well they actually write code. They can speak eloquently and say all the right things. That’s the talent of their salespeople. You may even speak to some of their engineers and think they’re brilliant – and maybe they are. But “brilliance” doesn’t necessarily translate into superior software delivery. Software projects fail over 70% of the time (according to the benchmark 2015 Standish Group Chaos Report) and very rarely do you hear that blamed on the poor quality of the developers. “Well, yes we were late, but what did you expect? All of our developers are below average in skill…,” said no development manager, ever.

There’s only one thing that matters when judging the likelihood of receiving a quality software product on time and on budget: the company’s history of delivering quality software on time and on budget.

Nothing that they say about themselves matter. The only thing that matters is what their past customers say about them. So, ask around.

There are references and then there are references

Well, that’s obvious - asking a prospective vendor for references is de rigueur. Typically, the company will provide 2, or maybe 3, customers for you to speak with. That seems right, right? I mean, how many calls do you really want to make?

It’s not enough. Not nearly.

Every company has 2 or 3 go-to customers that will say nice things about them. So, they get used a lot. Perhaps there are relationships involved that transcend work, or maybe they’ve just made those customers particularly happy. Regardless, even a small, new company can usually come up with a few people for you to talk to.

But think for a minute what that means.

Have they only had 2 customers? Or have they had dozens, but only made 2 of them happy enough to be a reference? In either case, is that someone you want to do business with?

A company that serves, say, 10 customers a year, and has been around for 5 years, will have had about 50 customers. Hopefully, a substantial fraction of those 50 would be happy with the work they did. So then why would they only offer you 2 people to talk to? Or 3? Or 5?

Ask them for 10. Or 12. Or 15. If they can’t provide you with that many, ask “Why not?” Have they not had 10 customers? Or have they not made 10 customers happy? It’s one or the other.

Regardless, if they can’t give you 10 or 15 references, ask them for a list of customers -- a complete list, not just a few. Then – after you have the list, not before – ask them for the name of the person they worked for at each of those customers. There had to be someone responsible for the project. If they say that the person is no longer with the company, that’s OK – get their name anyway. Then look those people up on LinkedIn, Facebook, Twitter, or whatever. Reach out to them and ask about their experience with the company.

You only need a few minutes of conversation to understand how the project went, how the company delivered. Most people will be happy to spend 5 minutes with you on the phone – whether their experience was good or bad. Don’t stop with one – call and talk to at least 5. In about an hour, you can talk to 10 of their customers. You’ll be surprised at the things you hear and then you’ll know the truth – or at least you will have an idea of the quality of work you should expect.

If delivering the project on schedule and on budget is important to you, is it worth an hour of conversations? It is the only way you’ll know the truth. Everything else is just hype.

Calavista claims that over the past 2 decades, we have completed over 100 projects, and delivered well over 90% of them on time and on budget. If that’s true, then there should be scores of customers who are happy with our work, and who should be glad to speak to a prospect.

There are. So, we lead with that. The first thing we’ll do when a prospect indicates serious interest is to give them a list of recent customers who will speak to them about us. To keep relevance, we typically limit that list to customers we’ve worked with in the past 3 years. That list typically has about 20 names on it from maybe 15 companies.

This just seems obvious to us. If you are looking at a company that will not (or cannot) provide this kind of list, you probably really need to understand why.

When you’re looking to spend a large sum of money on a software project, you need to do your homework. It may take a few hours – maybe even a day or two. But in the scheme of things, what’s the cost of that compared to the cost of a failed project?

And finally – once you’ve settled on a company to work with, and you complete the project (or don’t, God forbid) – be open to someone reaching out to you on LinkedIn. Be honest and objective. Because someone may be betting their career on your candor.


Software Projects

Software on a Budget- Charting the Least Expensive Path to a Successful Delivery

Written By: Lawrence Waugh, Founder at Calavista


I’ve a friend who’s a software architect for a large (Fortune-100ish) financial institution. If you ask him what his company’s priorities are when working on a software project, it’s simple. The number one priority is security. Scalability is a distant 2nd. Everything else is noise. If it’s going to cost $10 million to patch a potential vulnerability in their system, they spend it. If a scalability project will take 3 years, they go and do it. Money, time, and resources are just not their concern.

Must be nice. But it’s not the norm.

I’ve been with Calavista Software, delivering software projects to our customers, for nearly 2 decades. In that time, we’ve delivered well over a hundred projects for various companies. Beyond that, I’ve had conversations with hundreds more who’ve gone in other directions. I’ve come to develop a pretty clear picture of what’s at the forefront of a customer’s mind when they’re thinking about having a software project done for them. That’s pretty simple too. Generally, it’s

1) Price
2) Quality
3) Time to delivery

Each of these is worth a lengthy discussion, but in this post, I’m going to talk a little bit about price. Or pricing, anyway.

One of the first things that comes up in most prospect conversations is, “how do you price?” Generally in this business, there are 2 major pricing models: Fixed Fee and Time & Materials. The names are self-explanatory: with Fixed Fee, you agree upfront what you’re going to build and how much it will cost. There are acceptance criteria, warranties of workmanship, and service level agreements on how bugs will be addressed when they’re found. Since time to market is usually important, there may be penalties for late delivery. The idea is that you know what you’re going to get, when you’ll get it, and how much it will cost, so you can budget both time and money for it fairly easily. It’s a familiar and comfortable model, which everyone who’s ever paid someone to mow their lawn, or cut their hair, or build them a house, is familiar with.

Time and Materials is the opposite. With T&M, you pay for the effort, not for the results. If you have particularly unruly hair, maybe the haircut costs twice as much as the other guy’s. Or if it’s really hot, and the lawn care guy has to take more frequent breaks to avoid heatstroke, you pay for that extra time. If permitting is delayed, the house may cost another $10,000.

Given that, it might seem obvious that Fixed Fee is the way to go on a software project and a lot of customers come to Calavista looking for that. In general, we think that’s a huge mistake, and here’s why.

What's wrong with Fixed-Fee?

The advantages of Fixed-Fee are obvious. And if a builder can charge a flat fee to build your house, why shouldn’t a software company charge a flat fee to build your software?

In fact, at Calavista we often compare ourselves to a General Contractor building your house for you. Just as a General Contractor will bring together and manage the various skilled resources needed to build your house (such as carpenters, plumbers, electricians, stonemasons, and such), Calavista likewise provides and manages all of the skill resources required to build your software application (such as Software Architects, Development Directors, UI/UX Designers, Developers, Testers, DevOps Engineers, Requirements Managers, Business Analysts, and such).

So what’s the problem? The problem is, that unlike lawn care, or a haircut, software development projects change. A lot. Even building a house is generally a far more stable effort than building software. A house starts with a blueprint, which you’ve spent a lot of money on an architect to produce. The blueprints cover literally everything that will go into the house. Building materials, plumbing fixtures, where each light switch is, and how it’s wired. Very few software projects today start with that level of detail. Rather, most software projects today are developed using an Agile methodology¹, which embraces change. The truth is that even meticulously-planned software projects – which take months, or even years, to specify – will invariably change and evolve over the course of the development effort.

So, if a project is taken on as a Fixed-Fee project, that means that every time there’s a change to the original plan, the change needs to be evaluated, the scope needs to be adjusted, and the price for that adjustment needs to be agreed upon. On most software projects, this will mean innumerable delays, and inevitably, cost overruns relative to the original budget. In addition, it tends to put the customer and the software vendor into an antagonistic relationship. That is, the customer is always working to make sure that everything in the contract is delivered, on time and on budget – while the vendor is always motivated to make sure that they’re not adding anything at all that’s not in the plan, because finishing early saves them money, while finishing late is costly.

I usually summarize it to a prospect like this:

If you approach a builder who’s built houses in your neighborhood for the past 20 years, and say, “I’ve got a half-acre – I’d like a simple ranch home, maybe 3,500 square feet, a patio, and a standard pool out back…” – they will probably be able to give you a rough estimate on the spot. If you sit down and flesh it out a bit more, they can refine to something quite accurate. Because they’ve built a dozen of those houses in your neighborhood. They know the problems they’re likely to run into and how to get around them. So, their estimate will probably be pretty much on target.

If it turns out that you forgot to mention that you wanted marble floors throughout, they can still help you meet your budget. “OK, if those are important, we can do that – but we may need to lose the crystal chandeliers or maybe the hot tub. Let’s figure out what we can cut to make room in the budget…” If your contractor is good and trustworthy, they will work with you to get you the house you wanted, for the budget you’d agreed to.

It’s the same with software development. Calavista’s been doing this for so long that we can estimate most projects quickly, with high confidence of accuracy. If something unexpected happens, we work with the customer to figure out the best solution. Using this collaborative approach, we end up being on time, and on budget, about 95% of the time².

Contrast this to the customer who comes in with a 20-page specification and wants a Fixed-Fee price. We have to tell them:

  • The spec they’ve written is fine, but it needs to be replaced with a 200-page version. It’s not sufficient to say, “there will be a connection to a 3rd party payment gateway a customer can use to make payments.” Instead, we’ll need to know which one they want to use and what SLA they’re signing up for. We’ll need to evaluate the 3rd party’s API and maybe prototype it out so that we know for sure it’s going to work correctly – because we’re on the hook if it doesn’t. And we’ll need to have at least wireframes of the payment page to see its complexity. Maybe even some high-res art.
  • Then we’ll spend a long time scoping it out. We’ll go through each of the 200 pages in detail and figure out how much we’d expect to have to charge them to deliver that, and then we’ll need to multiply that by 1.x. Maybe 1.25, or even 1.5 – because now all of the risk is on us. If some piece of it is thornier than we’d realized, we’ll have to eat the extra cost.
  • Finally, we’ll end up fighting tooth and nail about what’s in the spec, and what’s a change order. The customer will want to get everything we’ve committed to for the fixed price, and we’ll want to make sure they’re paying extra for everything that’s not in the spec.
  • In the end, it’ll take much longer to start, will cost more (even without change orders), and we’ll be at each other’s throats the whole time.

It’s a horrible way to do business.

When Fixed-Fee makes sense

OK, there are some projects where it makes sense. In addition to the advantages to the customer listed above, Fixed-Fee allows a degree of flexibility on the part of the vendor as well. For instance, if we have extra development capacity, it might make sense to just put those spare resources on the project and finish early. If it’s T&M, I’d have to charge extra for those resources, but with Fixed-Fee, the customer gets the product faster, and I’ve increased my utilization rate for my people. Everyone wins.

So, for well-scoped, well-understood, and small projects – meaning they’re not big enough that they really can drift far – it can be simpler for everyone to just bid the price.

Caveat Emptor

Finally – this entire post has assumed you’re working with a reputable – and good – software company. If not, then T&M will just be a crapshoot. In that case, it might be better to invest in a detailed spec that you can live with and avoid changes. Or best yet, find a company that is good, and reputable.

How can you tell if a company’s good, and reputable? I’ll get to that when I talk about the “quality” priority in a later post…

Summary

About 90% of the time, Calavista engages customers in a Time and Materials model. This allows us to be less conservative with our estimates (i.e. lower the Total Cost of Labor) – not because the customer will pay for overruns, but because we and the customer both want to keep costs under control. On a Fixed Fee project, Calavista assumes all of the risks of unpredictable delays and must swallow any overage ourselves. So, we charge more. With Time and Materials, we can work with the customer to figure out the best way around an obstacle, rather than just paying to plow through it, so we don’t have to build those risks into the cost structure. For this reason, T&M estimates are generally 25-30% lower than fixed-fee bids, while still providing an excellent likelihood of success.

But again, finding a good, reputable company to work with is paramount. More on that later.


¹ en.wikipedia.org/wiki/Agile_software_development

² 94.4% at last tally


code software development blue

Technical Debt Patterns: Overburdened Class

Written By: Steve Zagieboylo, Senior Architect at Calavista


This is the fifth part in the series, "Technical Debt Patterns."

Some important central class has several not-really-related sets of responsibilities, making it huge.

Robert C. Martin coined the phrase Single-Responsibility Principle (SRP) as one of his core guidelines in object-oriented design. This states that “every module, class or function in a computer program should have responsibility over a single part of that program's functionality, which it should encapsulate.” This does not mean that every class should have only a single internal value, but that every class should have a single core purpose, one thematic element over which it is responsible.

Often you’ll start with the best of intentions, where you consider one class, perhaps an abstract base class, to encapsulate some significant concept which may be implemented in concrete subclasses. In the course of development, you realize that there is some functionality that is common to these base classes that might be unrelated, or only marginally related to the core theme of the class, but it is a convenient place to put the added functionality. Perhaps related to persistence of this set of classes, or a validation check (which seems related after all, it is the validation of the representation of the core theme). Over time, this secondary responsibility turns out to need a couple of functions, not just the one, and suddenly the class has several major responsibilities, seemingly grown from nowhere.

Symptom

 
One symptom that can lead you to consider this pattern is that a particular class file is getting a lot of merge conflicts. It seems that frequently several people are editing the same file, so there are frequently overlaps. An alternative symptom is that people have avoided this issue by clearly delineating, in comments, the code for one responsibility vs. the other (or others). This is a clear sign that your class has outgrown its purpose and is failing the SRP.

Cost

The cost to living with this transgression ranges from high (when there are lots of merge conflicts) to low (where the code is pretty stable and this core class sees very little action). However, it is rarely worth living with it, because the approaches to fix the problem are generally pretty easy.

Solution 1: Simple Separation Within the Structure

This approach is really just a formalization of the segmented code structure described as a symptom. You separate the class into two classes and an interface (or two classes and two interfaces, if you want to be even more pure). First, create an interface which represents the functionality you want to separate out. Your IDE should have easy tools to do this, where you just pick the methods to pull out. Second, separate the class into two classes, one extending the other, where one has only the methods and supporting properties for the interface, which should leave the other with only the methods and supporting properties for the other major responsibility of the class.

Now you can move to the clients of this class, areas of the code that are calling it. Hopefully, most of them only think of the class in one of its aspects, so you can change their reference to it either to be the interface or the new, cleaner class. This part of the exercise will possibly illuminate for you where the muddled thinking on the original class has led to some sloppy code. Or maybe it will point out to you that this over-burdening hasn’t really been costing you much, in terms of a clean architecture.

Solution 2: Delegation

Another approach to fixing this problem is to move one responsibility completely out of the class hierarchy into its own, completely independent class or hierarchy of classes. Then you make the original class delegate all that work to the new, referenced class. You still separate out the secondary theme into a new interface, but rather than this being just a sugar-coating over the fact that you’re still doing all the implementation in a single concrete class (having inherited some of it, but it’s all still there), you actually move the implementation into a completely separate class. Clients of this class now need to make a separate call to get to the delegate before calling whatever method they wanted to perform.

This approach makes a lot of sense when you realize that you would really like to abstract out some of this second theme of responsibilities, and maybe that becomes a hierarchy of classes all on its own, orthogonal to the hierarchy that the core theme represents.


Waterfall vs. Agile

Written By: Jeremy Miller, Senior Architect at Calavista


 

In Episode 401 of Software Engineering Radio, host Jeff Doolittle spoke with our Senior Software Architect, Jeremy Miller about his experiences with waterfall and agile software methodologies. Jeff and Jeremy spoke about the history of these methodologies, and what elements of them has been either detrimental or useful.  In their conversation, they also dive into topics like Extreme Programming, pair programming, self-contained teams, the emergence of Scrum and which practices can best be leveraged to help a team experience true agility.

Listen to the full interview in the video below. Or visit IEEE Software to read their summary excerpt.

 


code software development blue

Technical Debt Patterns: Tree Rings

Written By: Steve Zagieboylo, Senior Architect at Calavista


This is the fourth part in the series, "Technical Debt Patterns."

Tree Rings occur whenever you have wrappers around wrappers, sometimes several layers deep. Sometimes this happens because a core of important code is too complex or too fragile for anyone still around to be prepared to edit it. Maybe the core represents an API that is called by code outside.

Developers have been afraid to edit a fragile bit of code, so new functionality is made by putting a layer around it and calling in. This can happen multiple times, and you can tell the age of a library by the number of rings around it.

Unit Tests (As Always) Analysis Step One

First, identify the rings, if there are two, or three. This is not as straightforward as this simple instruction makes it sound. Sometimes there are layers to an API that make perfect sense and are a good architectural choice -- as Mark Richards says in Software Architecture Patterns, it is a good idea to have a clear separation between the Presentation, Business, Persistence, and Database layers in the software. You don’t want to look at these layers and declare that they are tree rings.

Where you are likely to see Tree Rings is inside the Business Layer, and then it bubbles up to the Presentation or layer. In a web application, this is the REST API layer. When you see more than one Resource file (or REST API file) that sit over a given set of entities in the Persistence layer, that’s one sign that you might have a problem. Sometimes it isn’t a separate file or set of files, just an entirely separate section within the files, with a bunch of APIs that no one really owns any more, but then a bunch of new ones that replicate or overlap significantly the old ones. Sometimes they will even call the old ones, then filter or merge or otherwise transform the results.

The other time you will see this problem is in the Persistence Layer, when too much Business logic has gotten pushed into it, or, more likely, there was not initially a clean separation of Business and Persistence, but then someone added another layer because it was too muddled.

Analysis Step Two

Now that you’ve identified where the grunge is, figure out where you want to head but don’t start those changes yet. This is where you probably need to add unit tests before you proceed. Work out what the outside world really depends on from these inner pieces, and make thorough unit tests for them. If there are other parts of your own code that have been sticking their fingers into your inner rings, then make wrappers for those inner parts, possibly in the outer part where the API should have been in the first place, and change them to call the new API.

Finally Making Changes

Finally, you can work out what the right layers are. Make sure that the business logic is no longer in the Persistence Layer, and that you have only one, cohesive business logic class for each concept. If those classes are getting too big, then you possibly want to refactor your architecture so that the concepts are more cleanly defined and delineated.

If your unit tests are comprehensive, this is something that you can do over time. But that means you’ll have to budget that time in. You can’t just do the analysis and then congratulate yourself. Pick the worst one, where there are two or even three Business Logic wrappers around some set of the persistent entities, and clean up that one mess. Then you’ll have a good idea of how much time and effort it takes, plus you have improved your average code cleanliness by quite a bit, since you took your worst section and (hopefully) made it one of your best.


Key Indicators for High Performing Software Teams

Written By: Andy Fruhling, Chief Operating Officer at Calavista


It’s great to hear someone reference a book that you have recently read. It gives an instant level of rapport and usually several good conversation topics. I recently had this experience with two of our customers as they mentioned an excellent software development book called Accelerate: Building and Scaling High Performing Technology Organizations by Nicole Forsgren, PhD, Jez Humble, and Gene Kim. This book outlines software development best practices and should be, in my opinion, a starting point for anyone who wants to have a high performing software development team or organization. High performance software development does not occur by chance. Repeatedly delivering high value, high quality software requires a combination of:

1) Strong organizational discipline,

2) proven LEAN Agile-based methodology with automation wherever possible,

3) significant talent and experience that executes consistently, and

4) a commitment to continually improve process and tooling.

My oldest son is starting to apply to universities and will be taking some standardized tests over the next few months. What if we had a standardized test for high-performing software development teams? Perhaps you are thinking “His mind is starting to wander after too much binge-watching TV shows” OR perhaps you are thinking “This is great time for software development leaders to survey their team’s effectiveness and look for areas to improve.“ Either way, I thought it would be fun to turn the information from the book into a simple standardized test that anyone on the team could complete in a few minutes.

In Appendix A, the authors identify 24 key capabilities of high performing software development organizations. These capabilities are classified into the following 5 categories:

Continuous Delivery: Consists of 8 key indicators around software development tools and automation (aka Continuous Integration and Continuous Delivery or CI-CD). This is really the basic foundation of high-performing teams and worth 40 points on the test.

Architecture: There are only 2 indicators in this critical area. While CI-CD is the foundation for high-performing teams, Architecture is the foundation for the actual software the team is building.

Product and Process: Consists of 4 indicators that gauge the interactions with key product stakeholders around product and process.

Lean Management and Monitoring: With 5 indicators, this section looks for sophistication and efficiency in your operations with monitoring, dashboards and LEAN methodology.

Cultural: The last section moves further up the needs hierarchy with 5 questions on the leadership and culture of the organization.

Converting each of these capabilities into a question creates a simple, standardized test and allows us to have a little fun. Answer each question with a value from 0 to 4 where:

0 = Not happening today, i.e. “It’s on our To Do list, but not there yet!”

1 = Occurs occasionally in some areas, i.e. “Some people do this individually, but not standard practice.”

2 = Occurs periodically on some parts of the team, i.e. “Many team members are aware and have good intentions, but it is not happening on a regular basis.”

3 = Usually, but not always, i.e. “It’s part of our standard process, but we still seem to miss it at times.”

4 = Almost always, i.e. "It’s part of our DNA and just how we operate."

Once you have answered all the questions, sum the points per category and enter this value on the category title line. To get an overall grade, total the points for all sections and add 4 bonus points just for taking the test. This will give you an overall score from 0 to 100 with 4 easy points for just taking the test! Give yourself a grade using the standard schoolwork approach of “C” for scores in the 70s, “B“ for scores in the 80s, and an “A” for scores in the 90s. If you scored less than 90% on any category, you may want to review the sections of the book that are most relevant for that category.

How many software development teams score an “A” on this assessment? Whether your team scored an “A” or a “B” or perhaps something much lower, we can all find ways to improve our teams across these capabilities. We do well across each of the categories, but I would like to see us improve our automation and dashboards around the performance metrics.

Let us know your thoughts on this test. It would be great to hear feedback on areas where teams are doing well and where we as an industry need to improve!

Click to view and download the Calavista High Performance Checklist


code software development blue

Technical Debt Patterns: Bilingual Required

Written By: Steve Zagieboylo, Senior Architect at Calavista


This is the third part in the series, "Technical Debt Patterns."

This problem refers to the developers speaking a different language about the problem domain than anyone else, including the users. It is a lack of what Eric Evans refers to as “Ubiquitous Language,” the term Eric Evans uses in his book Domain Driven Design. He explains (correctly) that the developers should derive their entity names from the subject matter experts (SMEs), so that they are using the same language when they speak to them. This vastly simplifies the conversations with the SMEs and other users, with marketing, with documentation, with your own user interface!

Sadly, in my 35+ years writing software, I have never once been on a project where these problems didn’t arise. Names change, specs change, marketing comes down with a new dictum, there’s always something. What we called a Cube yesterday is now called a box; Filter is now Selector, and so on. So now that it is there, what are you going to do about it?

Step 1: Identify the terms that have multiple names.

Is it just one major object, or is it dozens of little objects strewn throughout? If you haven’t done so already, make a dictionary of all the domain entities, including both (or all!) their names in developer-speak, marketing-speak, and SME-speak. The beauty of this step is that it is going to be used no matter how you end up deciding to tackle the problem. Put your glossary somewhere that everyone knows where to find it, where you point new developers as one of the first things they see. You should be using, for developer documentation, some sort of wiki that ties well into your issue tracking system. Put the glossary front and center, and then link to it frequently.

Step 2: Identify the scope of the problem.

Usually the problem is more than just the class names that refer to these dual-named entities. There are argument names, member names, and local names that are just a lowercase version of the entity name; there are usually multiple occurrences of each named entity, with data transfer objects (DTOs), service classes, unit test classes, and more; there are database tables -- changing those names means a migration; and there may be a public API that would be a huge pain to change.

If you want to be able to follow file history, then good cooperation from your source control system is a must.

Another consideration is your source control system and its ability to track filename changes which is required in most languages if the class name changes. If you want to be able to follow file history, then good cooperation from your source control system is a must.

The last element of scope is the most important: Is your product one that you sell copies of the software to customers or one where the only commercial version is a single instance that you host and sell access to? In the former case, you probably maintain different versions, with point and sub-point releases. If your new development is on version 7.x, but you still support 6.3.x and 5.8.x, then your transition period where developers will have to develop in both languages becomes a huge nightmare. If that’s the case, I would suggest that just good documentation and socialization of the problem is going to be good enough, because actually fixing it is impossible -- those old names will still be in your older versions of the code.

Step 3: Change Ahead!

Plan when it is going to happen, possibly just after a major release when everyone is going to be taking a breath.

If you’ve decided that you do want to fix the problem, the biggest challenge will be timing and branches. Plan when it is going to happen, possibly just after a major release when everyone is going to be taking a breath. Make sure the developers all have their code checked in and merged to the main branch, because these changes are sure to cause merge conflicts with everything. Use the refactoring tools in the IDE just to change the names of all the classes, and don’t bother with the secondary uses, the member names, argument names, and local variables, unless the refactoring tools will do this automatically. Now get it all checked in and run your unit tests. If this goes smoothly, congratulate yourself because you’ve done better than I ever have.

The next step, if you’re going to do it, is to take the database tables. Because this needs a migration it will take longer. If you are changing column names within the tables, it will take longer, still. Fortunately, this should be reasonably isolated, so this can be drawn out and you can let the developers start making branches again. Honestly, in the times I have attempted to move to the Ubiquitous Language, I’ve never changed the database table names. I just documented in the few classes that touch the database directly, and kept my glossary up to date.

Summary

Of all the Technical Debt Patterns, this is the one that I would most likely recommend that you don’t try to fix it, just mitigate it with good documentation. First, it is a minor inconvenience but not really crippling unless you really have a lot of churn on your development staff. It is more of a pain and an embarrassment when you are introducing new developers to the team, and once they are used to it, it doesn’t cost that much. The other consideration is how much of a moving target it is that you are aiming at. If the product is a new, world-changing paradigm (and what isn’t?) then you can count on marketing changing all the names again in another quarter. They might even change back to what you used to have. So, unless you have a pretty stable product, I would recommend just to live with it.


software problem

What's Your Problem?

Written By: Daniel Kulvicki, Solutions Director at Calavista


I know. The title is a little in your face, but I have always asked this question on each of my projects. Instead of focusing on a solution, focus on the problem that you are solving and keep that focus through the entire project lifecycle. Most projects spend 90% of their time on the solution and only 10% on the actual problem space. We should be putting equal weight to the problem space and the solution space. Let us look at the differences of the problem space versus the solution space.

Problem Solution Space
Figure 1- Problem Space vs. Solution Space

Problem Space

"A market is a set of related customer needs, which rests squarely in problem space or you can say “problems” define market, not “solutions”. A market is not tied to any specific solutions that meet market needs. It is a broader space. There is no product or design that exists in problem space." (Ref 1)

What I have found in the past, is that when you ask customers what problem you need to solve; they come back with a solution. Solutions are great for customer feedback to ensure your problem is being solved. However, you must first identify your core problem. My favorite question is “What are you trying to solve?” and it usually takes about 3-4 iterations of answers to that question to get close to the real problem space. Eventually, a “voila!” happens and it just seems easy after that. Until you start working towards the solution.

Solution Space

"If I speak of solution space, any product or the product design — such as mock-ups, wire-frame, prototype, depends on and is built upon problem space, but is in solution space."

Everyone loves the solution space. It is hands on, validates, and is something new! How quickly have meetings turned to whiteboard sketches and tons of ideas that gets everyone excited? All of this excitement is great and is needed when working in the solution space. But, don’t forget the problem you are solving. Everyone might start off with the right core problem to solve, but as the solution progresses; that problem may change, and no one notices it as they drive to their “awesome” solution. That is why you need to have a certain discipline as a project is executing to step back into the problem space in order to validate the solution.

Product Discovery

Product Discovery is essentially an Agile approach to manage your problem space. Product Owners on an Agile project tend to manage the backlog, but not the problem space. Hence, the need to build in Product Discovery as part of backlog grooming. Try it sometime in a future project. With the right discovery process, your projects will start to come in on time and budget like they do at Calavista.


code software development blue

Technical Debt Patterns: Abstraction Overlooked

Written By: Steve Zagieboylo, Senior Architect at Calavista


This is the second part in the series, "Technical Debt Patterns."

The Abstraction Overlooked pattern is where you have some concrete class that has a “type” of some sort, and you find yourself basing some of its behavior on its type, either through if-then-else or switch statements. Often this occurs because the original programmer didn’t realize that there would be more than one type of this object, either because requirements have changed, he just didn’t think about it, or the entire project has grown larger than anyone ever imagined.

Example

Say you’re writing a tool for stock brokers to track the assets of their clients. One aspect of a client is his cash account, which your transactionally-sensitive code draws from on buys and adds to on sells. Your code includes a test on a withdrawal that you aren’t drawing more than is in the account, and rejects the transaction if it is. Your code works great, and the stockbroker is happy. Then he comes back with a new feature, Premium Customers. One aspect of a Premium Customer is that he is allowed to overdraw the cash account by some fixed amount, because we trust him. You edit your withdrawal code to check if this is a Premium Customer, and it now allows the transaction if it is within his overdraw limit. This is literally less than a line of code – just an extra test in the if statement. Then another type of customer is allowed to attach his bank savings account to his cash account, and you’re supposed to change the code to draw from that on an overdraw. And there will be more – you should have made the account an abstraction.

The Cost

The biggest aspect of the cost is not ongoing development, but ongoing quality and testing.
The cost for this pattern is a subtle one for many developers, because the biggest aspect of the cost is not ongoing development, but ongoing quality and testing. Every time there’s a new way a special type of account behaves, the developer is now editing code that is used by all accounts, with some possibility of introducing a bug to one of them. Sure, you have unit tests, and I’d even bet that, for this example, they’ve got enough coverage that you wouldn’t miss something. But can you say that when it is something less carefully tested than monetary transactions? As the cases get more complex and there are three or four places where there’s a behavior change based on the type, are you really sure you haven’t missed one?

The Fix

The fix for this problem is usually well-contained, and, if you do have those unit tests, fairly easy to confirm is correct.

1. Scope the fix first by declaring the class to be abstract and making a single concrete version of the class that has literally nothing in it. Then rebuild and see how many errors pop up. They will be all the places you’re calling the constructor of your now-abstract class. Ideally, your only errors will be in the one place that owns this object and in the unit tests which are specific to it. If there are a lot more, you might want to take a step back and ask yourself if the missing abstraction is a level higher (or at both levels). If you’re satisfied with the number of errors, make a factory to create the correct instance of the class, thinking about what concrete classes you’re going to end up with and what the factory will need to know to create the right one. (I’m fond of making the factory a static method of the abstract class or interface, but there are people who hate this approach and always want a separate class with this responsibility. I’m not quite willing to say they are wrong, but I’m also not going to change the way I do it. It’s a trade-off of clarity vs. simplicity, and I usually go for the latter.)

2. At this point you might decide you want an interface rather than an abstract class; that’s almost never a bad idea, even if there is a single abstract class that all the concrete classes extend. Extracting out the interface forces you really to think about what functionality is fundamental to the concept and what is implementation detail. I like making the abstract class, though, even with the interface. If you found yourself here, there’s probably a lot of functionality still that is common to all the concrete classes, and that code can stay in the abstract base. Let the highest level thing, the interface or the abstract base, keep the name by which the rest of the world knows this concept, and make the concrete classes have new names that describe what they are.

3. Then you have a pretty straightforward process of identifying what the concrete classes should be and moving the code out of the if-then-else or switch blocks into the appropriate location. Often you’ll find that the abstract methods which the concrete classes are overriding are protected – they are not the methods being exposed through the public interface, just a small part of them. There’s nothing wrong with this approach, but don’t overdo it, either. The abstract methods should make sense according to what they accomplish, not according to the details of how they get accomplished in the special cases you care about.

The abstract methods should make sense according to what they accomplish.

4. Once you’re a little way into the process, try to imagine the most extreme concrete class you might ever be expected to make. Ask yourself first whether or not you’ve passed all the information to the factory that you would need in order to know to create this. Then ask yourself if the abstract methods you’ve created would support the special cases that this class represents. Don’t add new abstract methods that exist only to support this imaginary case, but possibly rethink the ones you have, and make sure that the right information is available for them. It’s hard to quantify how, exactly, this experiment will inform the process, but I’ve almost never come out of it without some new bit of data.

5. The last step is to revisit your unit tests. If those tests were creating the original object directly, they need to change to call the factory. Take an inventory of all the unit tests to be sure all your concrete classes are being thoroughly tested, even all the methods that are not specialized in any way. You might want to create a new class AccountTester (for our example) that tests all the methods of any account, with parameters passed in for the expected results. Then your individual tests will consist of calling the factory, creating a helper with all the right parameters, then calling it. Think how happy you’ll be next year when you find yourself writing yet another concrete instance of this class.


The Fundamentals of Continuous Software Design

Written & Presented By: Jeremy Miller, Senior Architect at Calavista


CouchCon Live is a single day virtual technical conference focused on connecting and growing our vibrant tech community! We're bringing quality technical content to a virtually connected community. Whether you're a new developer or have been working in the industry for years, we know you'll meet other great people and learn something new!

 

https://www.youtube.com/watch?v=v9icxKMJ9PA&t=108s

 

The Fundamentals of Continuous Software Design

Scrum completely dominates the landscape of Agile Software Development these days, but it’s always been a little focused on project management and a little bit light on specific software engineering practices and guidance. It’s unfortunately easy for Scrum projects to drown in technical debt while the team tries to keep up with the drumbeat of constant sprint deliverables.

Harking back to earlier Extreme Programming ideas, let’s review some of the fundamentals of continuous software design and how we can keep our codebases from turning into a giant mess as the system evolves. With some concrete examples, let’s dive in and learn more about reversibility, the importance of testability in software design, the ‘last responsible moment’, striving for simplicity now (YAGNI) without cutting off a pathway to more complex behavior later.