

Develpreneur: Become a Better Developer and Entrepreneur
Rob Broadhead
This podcast is for aspiring entrepreneurs and technologists as well as those that want to become a designer and implementors of great software solutions. That includes solving problems through technology. We look at the whole skill set that makes a great developer. This includes tech skills, business and entrepreneurial skills, and life-hacking, so you have the time to get the job done while still enjoying life.
Episodes
Mentioned books

Apr 2, 2021 • 15min
Destructors And Cleaning Up An Instance: Object-Oriented Design
When we get to the end of our use of a class instance, we need to clean up after ourselves. This is where destructors come into play. They are similar to constructors in a mirror fashion. While a constructor creates an instance, a destructor removes an instance. Destructors And Resource Release Many languages have a default destructor, much as they have a default constructor. These methods likely free up some pointers behind the scenes. However, we also have resources and properties or even notifications that may be needed as part of this process. That leads us to a process that effectively undoes the creation and initialization steps. We first release resources (reverse the initialization). Then we remove the instance from memory (reverse the constructor). The Important Properties The challenge with a destructor and cleanup is that many languages do most of this work for us. The tasks of memory initialization and pointer creation are done under the covers. Therefore, we can leave the default destructor as is and let the system manage those things. However, we do often have non-simple attributes like child instances and resources to release like file handles. These complex attributes and initialization steps are critical to review and address in our destructors. Keep It Simple With all of the above in mind, we also need to consider what happens when a destructor fails. Therefore, it is helpful to have a close or cleanup method that we can call separate from the destructor. It may seem like splitting hairs, but there is value in handling releasing resources separate from destroying an instance. This impact comes from destructors often being called more often than we think. A fat destructor can dramatically slow performance, just as we see in fat constructors. This multiple-step approach to cleaning up makes it easier to handle each step at a time. Thus, potential exceptions are addressed individually rather than treating them in a bunch. That smaller scope will help you avoid headaches and synchronization of getting the system cleaned up.

Mar 31, 2021 • 15min
Constructors And Initializers In Object-Oriented Design
When we create an instance of a class, we often need to do some initialization. Constructors and initializers achieve this goal. These are two different ways to get our data into an instance and are an essential part of our design. In this episode, we examine the design decisions we need to make as we decide how to use these common methods. Constructors And Initializers - The Distinction A constructor and an initializer method can be thought of in very similar ways. However, there is one particular trait that differs between the two approaches. A constructor returns an instance of a class, whereas an initializer sets values on an instance. This may seem to be a minor difference. It is not. There are situations where we need to create many instances of a class, and a "fat" constructor can lead to performance issues. The creation of an instance is an important operation. Thus, it is best to complete it in as short a time as possible. That is where an initializer comes in. We can create an instance quickly and then take our time populating that instance (i.e., initializing it). A No-Args Constructor Many languages include a default constructor for classes that takes zero arguments. This provides a quick way to get an instance. I personally find these important and highly useful in extending classes. The exception to providing a default constructor is when you need to provide limited instances or some level of instance management. Adding Parameters Once you start adding parameters to your instance creation, you should consider an initializer. That provides a cleaner way to create an instance and then populate it. You also give the developer the ability to "lazy load" data, for that instance. That is an important option in large systems and large classes. A good initialization routine also provides an opportunity for a mirroring cleanup method that makes it easy for a developer to control resource usage within classes. A few core parameters for an instance may be convenient, but once that list gets long, it can slow the process. It is better first to get a valid instance and then do something with it.

Mar 29, 2021 • 14min
Static Attributes And Methods In Object-Oriented Design
In this episode, we look at how to use static attributes and methods in our class design. These are important but can be over-used. They can even be a supported way to break the object-oriented nature of our program. We can "static" our way into a design that can not be extended. Therefore, we need to use these sparingly and with consideration about how they may limit our solution. Static Attributes It always helps to set the stage for these types of discussions. Static attributes and methods are not supported by all languages, nor is that always the proper terminology. For our purposes, a "static" is a class level value or function. Thus, there is only one version of these items. There is not a version on each instance. For example, a class-level attribute of "counter" will have the same value for all instances. When the counter variable is altered, all instances see that new value. As you can see, this approach will tie our instances together in a loose way. They are now linked through the static properties. The Singleton The software pattern "singleton" is an example where static values and methods are useful. They are almost required to implement this pattern properly. In this case, we have a single instance only for a class. This could be to provide global values or to limit access to resources. We might even blur the singleton into a limited number of instances. This option is a great way to have a small number of files open or database connections. A Static Anti-Pattern One of the uses of a static value is as a way to pass around or share that value. This approach can be used to avoid method parameters or a data store. While that is a valid way approach, it can be limiting and error-prone. A static value opens us up to the idea of race conditions. What happens when two bits of code try to update the value at the same time? It will be cleaner for us to pass values and limit access through properly designed methods, even though the direct approach is likely going to require less code. This feature provides us a lot of power. However, with great power comes great responsibility. Design responsibly.

Mar 26, 2021 • 16min
Software Design - Finding Balance With Coupling And Cohesion
We have spent a few episodes looking at cohesion and coupling. Now it is time to find balance in these two software design approaches. Each approach has strengths and weaknesses. Therefore, our best approach is to combine the strengths while offsetting the weaknesses. This best-fit approach is not as difficult to achieve as it may seem. Cache The Main Data The large object approach allows us to access data and methods quickly. We have a short path to get to these items as the layers of abstraction have been minimalized. The greatest value of this approach is when we have data or methods that are often used. There is little value to this efficiency for items we rarely utilize. For example, think about a daily report vs. a monthly report. The calculations that generate the monthly report can be less efficient and time-consuming because they are rarely utilized. A cost of 15 minutes for a feature is only paid once a month. The daily report has a higher value of performance. That same addition of fifteen minutes adds up to a loss of over a day per month. More iterations equate to a greater value for performance improvements. The A La Carte Approach We can push our primary data and features into a few large objects. That helps us with performance. However, it may seem overly taxing to a system to load all of the lesser-used data and methods in a single class. Instead, we can utilize smaller objects that can be quickly instantiated and freed for less frequent needs. The overhead cost of initialization and cleaning up these small objects is often a wash. We do not use them much. Thus, the slower performance has little overall impact on our system. A Flexible Software Design We pointed to flexibility as a strength of the coupling approach. However, we did not mention that coupling can be done with a combination of large and small objects. We see this thought process played out in patterns and frameworks like the flyweight and object factories. Even big things can have some small (replaceable) moving parts. That is the key to the blended approach. Keep the common things close and store the less-common features in easy-to-initialize small objects.

Mar 24, 2021 • 17min
Coupling - A Smaller Object Approach To Software Solutions
In object-oriented software, we talk about the concept of coupling. Put simply; this is a small object approach to our solution. It is the opposite end of the spectrum from large-object, or monolithic, designs. In my experience, a developer's bias towards cohesion or coupling often comes from their background. Those that have come from functional languages and platforms are more comfortable with cohesion, while those that built components tend to use coupling. Coupling Strengths It is hard not to point to flexibility as a primary strength of this approach. It stands to reason that the more points of adjustment available, the more flexible the solution. This example is easy to see in physical objects. Remove all of the joints in your body, and you will be less flexible. Likewise, return to our Lego example and consider what you can build with smaller as opposed to larger blocks and structures. Smaller Impact Another important strength of coupling is the ability to make changes with a smaller requirement of validation. Thus, we can make improvements or changes and have less testing required. This benefit can be critical to maintaining large systems without endless regression tests and unworkable release cycles. We do need to verify we have not introduced unintended changes. However, we have the ability to make tighter changes that are easier to debug. Where Does This Go? The challenge with coupling is figuring out what goes where. This conundrum is not different from the levels of normalization in a relational database. There are situations where an attribute or method has overlap in the classes that use or need it. This straddling of classes can make it challenging to place our bits of code properly. On the other hand, those situations often point us to where a third-class shared by the two primaries is the best solution.

Mar 22, 2021 • 16min
Cohesion - A Big Object Approach To Design
This episode focuses on cohesion and the idea of using fewer large objects to solve a problem. This approach is often considered the opposite of using more smaller objects. We will find out that there are ways to combine these two different approaches as a best-fit method. Cohesion Strengths We have already defined and provided a summary of cohesion. Therefore, we can dive right into some specifics and strengths of this approach. I find simplicity to be one of the most apparent strengths of these solutions. While it provides a sort of "junk-drawer" approach in some cases, it also means we do not spend time deciding what goes where. When done properly, we can see this approach as having all of the important things you are working on sitting on your desk. Nothing is filed away. Thus, access is quick and easy. The Performance Aspect The lack of a need to "find things in your file cabinet" provides us efficiencies. In the code context, we have fewer abstraction layers to dig through for a value or function. Everything is readily available to the code, and permissions are a non-issue. This configuration provides for improved performance. Think of it as the best way to get something done is to do it yourself. Some developers see it as getting a task done quickly rather than creating classes to break the task into smaller pieces. Power In Simplicity There is power, as well as beauty, in simplicity. The product lines of Apple are a commercial example of this concept. We can remove a lot of time and decision points by limiting options. In the cohesion context, this comes from us knowing where a property or method belongs. We also spend less time worrying about what we should be able to see an attribute or method. When we take this to an extreme, we can see a near return to the old single file, functional approach to designing a software solution. We get to focus on functions over where they "live." When the solution is small, this all will make complete sense. Why complicate a solution needlessly?

Mar 19, 2021 • 15min
Cohesion and Coupling in Object-Oriented Design
Cohesion and coupling are options that are often discussed in object-oriented design circles. They are two ways to approach a solution. On the one hand, the solution can be a larger, self-contained approach. On the other hand, the solution can be a core that uses several "helpers" to achieve the objective(s). These are important options for us to consider as part of the overall OOD discussion. In this episode, we start with an overview of these common paths. Cohesion Defined There are many ways to think about Cohesion. However, I find it best to start with a common form of definition like the one found on Wikipedia. In computer programming, cohesion refers to the degree to which the elements inside a module belong together. In one sense, it is a measure of the strength of relationship between the methods and data of a class and some unifying purpose or concept served by that class. In another sense, it is a measure of the strength of relationship between the class's methods and data themselves. While we will not cover it at this point, note that there is an idea of a relationship among properties and methods in a class. This definition provides some foreshadowing in how we decide what method belongs where. Coupling Defined The ideas around coupling are much like cohesion. Therefore, let's start again with a simple definition like the one found on Wikipedia. In software engineering, coupling is the degree of interdependence between software modules; a measure of how closely connected two routines or modules are; the strength of the relationships between modules. The key concept here is found in the mention of interdependence between modules. It is a different focus from the inside of the module reference in our definition of cohesion. Cohesion and Coupling - Finding Their Place These two approaches are often seen as opposites. Thus you take one approach or the other in your design. However, that is not required. There can be some large objects with little coupling or large objects that are rather cohesive (in general), yet they have a substantial number of helper objects. These patterns of design do bring up the idea of consistency across a solution. On the other hand, they provide ways to handle different problems within a system in the best manner for that problem. The best way to look at these two options is to understand the strengths and weaknesses of each. Then we can find the best tool for the situation and expand our ways to solve each problem on its own.

Mar 17, 2021 • 14min
Property Design In An Object-Oriented System
One of the most prevalent topics of consideration in an object-oriented system is property design. We can keep them simple or create more classes. The first approach is simpler and faster to implement. However, we can use objects to provide hooks we extensibility and scaling out our features. There are trade-offs to be aware of, but we can use some guidelines to shorten the design process. Property Design Considerations For purposes of this episode, we will look at two paths available. We can use a simple type (native) or use a class to define a property. While we can also utilize collections as properties, those still boil down to one of these two paths. You will either have a collection of native values or object instances. A Software Upgrade A primary benefit of the object approach for a property is that it allows us to upgrade or "power-up" a class. A simple example of this is a greeting for a class. We can leave it as a string, or we can provide a greeting object. That object could start by displaying a greeting in English. When we want to upgrade the getting, we can add support for other languages or even an interactive greeting object. The Plugin Approach The above example can be viewed as a plugin. We can use this approach to provide a "quick and dirty" for the initial release and then improve it later. This pattern is excellent in an Agile environment in particular. We can build out functionality in one class. Then, we can inherit and extend that class later. The original features and functions are still available for instances built in the prior version. Yet, we can use the new approach for new instances. We get scalability along with stability. We have designed our solution for growth and flexibility. These are essential traits for an agile system.

Mar 15, 2021 • 17min
Class Relationships - When Has-A Shows a Relation
Our language can blur the distinctions of class relationships in designing our solution. The "has-a" determination is often confused by how the English language can translate those words. We also have to keep a context for assigning a class. Likewise, reality allows for data to be multiple classes in some cases, so we need to examine how those might be a hierarchy of some sort. Class Relationships - "Have" As A Pointer The confusing aspect of the English language is that we can "have" a relationship and a property. For example, you have an age, and you have a parent. The age is a property of being you while the parent is a relationship. This language blurring of properties can be confusing to those new to the idea of object-oriented design. Does It Stand On Its Own? The way to look at these different aspects with the same name is whether the target is itself an object. That is, can it stand on its own apart from the "owning" class. In our prior example, your age has no meaning apart from you. That age is not something you can give to someone else. Others have the same value for their age, but it is not the same age we are referring to. Your parent exists outside of you, and others can have that same parent. The Impact Of Change In the software world, it may help to look at what happens when the target property changes. Does it impact any other objects? If I change your name (a property you have), that only impacts you. It does not change anyone else's name. If your car changes, that impacts you and anyone else that links to that car. This is one of those data facets we see all the time. Do we copy a value, or can we have multiple pointers to it?

Mar 12, 2021 • 16min
Is A and Has A Concepts in Object-Oriented Design
The ideas of "is a" and "has a" are often discussed as part of object-oriented design. These concepts may seem simple and obvious. However, they can often be confused, and complex systems can blur the lines between them. We start a multi-part episode going over these concepts focused on how "is a" relationships work. Is A and Has A Defined These concepts boil down to simple grammar. For two objects, A and B, here are the options. A is a B if A has all of the traits of B. For example, a poodle is a dog because a poodle has the traits we equate to a dog. A dog is not a poodle, as some dogs have traits that are not shared with a poodle. A has a B when the entirety of B exists within A. A dog has a tail. The tail does not exist on its own away from the dog. More simply, a car has a color. In these relationships, multiple things can have the B part of the relationship. One Way Relationships For our purposes, these are one-way relationships. When A is a B, B is not an A. Likewise, when A has a B, B does not have an A. The color does not have a car; the tail does not have a dog. These definitions can seem to break when we replace names with instances. A father can have a son, and a son can have a father, but that is not a definition of contained properties. This example would be a relationship or pointers and not attributes that are contained. You have a height no matter what. You may not have a father if he passes away or something like that. As you can see already, grammar can confuse the situation, so we will continue to dig into these concepts and applying them.