Monthly Archives: September 2016

Computer Science Essentials for the Working Software Developer

Some key nuggets of knowledge toward writing good code are either not taught in school or are mentioned as esoteric theoretical knowledge and most people don’t realize how practical and important they are for competent, everyday software development work. Building software from components, assigning responsibilities to components, deliberately deciding how state is stored, coupling, cohesion, and cyclomatic complexity are essential elements of good software practice.

This the third article in the series on Starting in a Software Development Career.

When you write code you are solving problems: small ones, big ones, one problem after another. Problems you need to solve tend to be too big to solve with just a few lines of code. You have to take most problems apart, and identify smaller problems that make up the big problem (small ones that you can solve). These smaller problems are the components that you identify. To be successful at writing software that solves big problems, you have to be good at writing software components that solve a part of the big problem. Building software from components is the first critical skill to master for a software developer.

As you are taking things apart, identify which part of your code will do what. In other words, assign responsibilities to parts of your code (#1). A good component has clear responsibilities and collaborators to get its job done. Of course, as you are taking the problem apart, you must keep in mind that you will have to reassemble the parts in order to make the system work.

Each part of the software has to be responsible for doing some work, and you have to decide what that work is. Each line of code, each function has to be responsible for something, otherwise why would you include that line of code in the system? Assigning responsibilities to parts are possibly the most important decisions that you make during the design of the software system.

But why would you want to assign responsibilities to software parts? The short answer is to cope with complexity. This allows you manage the complexity of not having to think about how the part is implemented. As you are assembling the parts, what matters is the part’s interface and its responsibilities.

A subset of important decisions as part of the responsibility assignment are deciding which part of the system should hold on to state. State is a term that collectively refers to any data that the software holds. This state can be short-lived or long lived. Sprinkling the state across a large swath of the system will make it difficult to reason about the behavior of the system.

A good strategy is to make a large portion of the system stateless, sometimes referred to as purely functional. Make sure that this part of the system doesn’t have any side effects, in other words each function only operates on its input parameters and returns its results for others to use.

After graduating from college, like many others, you probably thought that most of what you were taught will not be all that useful during your “real” work. Interestingly enough—if you are a computer science graduate who develops software—most of the things you learned will come in handy at some point in your career, provided you know when and how to apply them. Here are three esoteric sounding things that are present every working day, even if you don’t recognize them: coupling, its close relative, cohesion, and their friend, cyclomatic complexity.

As you are deciding on the responsibilities and where to store state, you need to pay attention to coupling, cohesion, and cyclomatic complexity. Coupling is a connection or dependency between two software parts and it’s a measure of that relationship. Coupling exists, because it must, in every software system. Without coupling, or in other words, without being connected to or dependent on one-another, one function could not call another function.

A certain amount of coupling is necessary for a system to do its job. The problem appears when in a system there is too much coupling. For most cases it is best to have as little coupling as you can get away with. As systems evolve, the amount of coupling can become troubling. When there is too much of coupling it becomes difficult to change the system without creating undesirable changes to parts of the system that you didn’t intend to disturb.

While coupling looks at the relationship between parts of the software system, cohesion looks at what’s happening inside a software part. Specifically, cohesion describes how strongly the responsibilities of a software part (be it a function, class, component, module, subsystem, or even system) are related to one another, and how consistent those responsibilities are.

A software part is called cohesive if the software part’s responsibilities are focused around a single purpose and form a meaningful unit. Why is cohesion important? If we keep related things together, then we can reduce the churn caused by changes in the system. If you ensure that the software parts you write are cohesive, meaning that the related responsibilities are kept together, then as a result they don’t have to talk to too many components, thus they will have lower coupling.

So far we looked at a software part and said that it’s cohesive if its responsibilities are related to each other, and it has low coupling if it doesn’t have to talk to a lot of other parts to get its job done. Next let’s see how well it gets the work done. The formal definition of cyclomatic complexity is that it measures the number of linearly independent paths through a function or procedure.

Empirically you can get a feel for cyclomatic complexity by looking at the function. When you see complex conditional series of if .. else if .. else if, if .. and you get the feeling that this looks pretty hairy, then cyclomatic complexity is probably out of whack. There are tools that measure the cyclomatic complexity number (CCN) of each function in your code. If the CCN is greater than 10 for a function, then there is a good chance that it’s difficult to comprehend that function and you should consider rewriting it.

By paying close attention to the assignment of responsibilities to components, state, coupling, cohesion, and cyclomatic complexity as you are writing software, you can make your code much easier to design, write, and read. Keep in mind that you are the primary reader of your code, since you have to go over it many times before its complete. The easier you make it to comprehend, the more likely that you will complete it faster and with fewer defects.

Happy coding!

  1. Larman, Craig. Applying UML and Patterns, An Introduction to Object-Oriented Analysis and Design and Iterative Development. Prentice Hall PTR. Upper Saddle River, NJ. 2005.

Your Professional Relationship With Your Colleagues

In some places software development is still regarded as a highly technical activity performed by a lone genius programmer writing fantastic code. That’s not quite the case anymore. While an individual can still write great programs alone, most programs require more than one developer (otherwise their completion might miss the market window). Software development has increasingly become a cross-functional team activity (even if the team in many cases is not located in the same office, or even on the same continent). Your ability to work with your colleagues has become a critical aspect of your success as a knowledge worker.

This the second article in the series on Starting in a Software Development Career.

Developing software is as much a team activity as it is an individual effort. Sure, there will be times when you will be designing and writing code on your own. Most of the time though you’ll be working with a design or coding partner, or a small team of 3 or 4 people on a multitude of collaborative tasks.

If your team is bigger than five people then it’s likely that you are on a multi-disciplinary team. Most team members will be software developers, but there will be other disciplines represented, too. As a person new to the profession, when you work with developers there are two important things that you can do to earn some credibility with them: (1) complete the tasks that are assigned to you, and (2) anticipate some of the questions that puzzle the team and do the legwork to look up the answers and present them to the team.

When working with developers find ways to assist them when they need it. As a new person on the team one of the best things that you can do is research things that the others need information on. When someone says: “Who has any idea how this XYZ API works?” then you can find the relevant documents and useful sample code to help them out.

In order for knowledge work to be effective, knowledge workers must specialize. This is true for software developers, too. There are developers who specialize on back-end or server-side development, front-end or user interface development, database development, mobile app development, mobile web development, desktop application development, etc. Some specialize on specific languages or platforms. And some are full-stack developers who benefit from the ubiquity of a language on both front-end and back-end that allows them to work effectively on the entire application.

Beyond developers, you will be working with quality assurance folks. They are often called in too late (if at all) to participate in the development process which makes things worse then it should be. You can do things better by going to QA and talking to them early about the work you intend to do and ask for their advice on how to avoid common pitfalls. You’ll be surprised how much better your code will work once you let them assist you from the beginning. They will also benefit because they won’t have to scramble to find out everything in the last minute, when everybody is upset that the product hasn’t been shipped yet.

You may also be working with a product manager who is leading the effort in defining what the product is. Product managers have many challenges and are getting pulled into lots of directions. When they ask for your help, find ways to assist them. They are capturing ideas that the team and the users have, clarifying the market need, and working with the entire team to put a product out to fill that need.

Business analysts and requirements analysts study a particular business and capture the knowledge in a digestible format for efficient consumption by the rest of the team. They convert obscure and difficult to grasp business intricacies into developable features by collaborating with product managers, quality assurance analysts, developers, etc.

If you are lucky, then your team will have at least one user experience (UX) professional. The UXers are the ones who make your software be user empowering instead of user aggravating. If you are not fortunate enough to have them on your team, then at least read up on elementary usability concepts and employ those techniques to make your software easier to use. A common mistake that we all make as developers that we design the software as if we would be the users of it. Sometimes we are the users, but most often we are not. (Then we end up like the little boy who gives his mother a firetruck for her birthday because that’s what he wanted to get for his.)

When it comes to working with your manager, a good starting strategy is to understand your manager’s goals and objectives. Based on those find a way to align your goals with their goals. This can be difficult, since there may not be a clear line of sight from what you do to what is expected of your manager. You may need to ask for help, which could be hard to get from a busy manager. So, then you do the next best thing: find a mentor who can provide you with guidance.

Mentors come in all shapes, sizes, and ages. In just about any size organization you will find somebody who can help you grow in your role, or who can help you grow your skills, or who can help you navigate the organization. All you have to do is find them. These are the folks who are ready to help you just for the asking. The benefits are usually mutual: they get somebody to whom they can pass on their experience and who can bring a fresh perspective into their world. And you benefit from their wisdom.

Sometimes your organization just doesn’t have the right person who can be your mentor. Then you need to turn to outside mentors. Look beyond the company and find user groups and professional organizations. There is a good chance that you will find somebody who will be glad to assist you or coach you. And, if all else fails, there are usually good online resources or good books to study on the subjects that can help you grow and achieve your professional goals.

There are other folks in the organization with whom you may rarely talk, but you should know that they also have an important contribution to make toward the success of your team. These are the folks in corporate operations (like administration, payroll, contracting, etc.), IT operations, etc. Without them, you’d have to do all the work that they do. Be grateful that they do a good job and so that you can focus on yours.