Develpreneur: Become a Better Developer and Entrepreneur

Rob Broadhead
undefined
Jul 15, 2021 • 23min

Trevor Ewen Part 4 - Extending Code

We wrap up the Trevor Ewen interview series with a discussion of building libraries and extending code.  While this is often a necessity, there are different ways it can be done to help separate your code from the core or to safely build on it.  Your desired approach will vary by application and the customers involved. Extending Code Safely There is often a right way and a wrong way to extend code.  We need to do this in a way that allows us to incorporate updates to the foundational source and not break our extensions.  It is also helpful to refactor extensions into using core functionality as libraries evolve.  Every tool and platform handles these "hooks" differently.  Therefore, we need to understand the core and our customization impact before we integrate things either too loosely or tightly. Supporting Your Work The other key consideration in building an extension or library is support.  Licensing may be an issue, but support and maintenance will always be a factor.  You are not committing to a solution for only today.  The solution needs to survive in the future and handle upgrades and fixes without falling to pieces.  A one-and-done library is not worth the effort.  When you plan on extending code, you also should plan for keeping that extension useful over time.  That is the same whether you build an internal library or are selling commercial software. Great Links for more From Trevor I had a great time doing this interview and reviewing the content during the editing process.  It is my hope that you got as much or more out of it.  Feel free to send questions (or business) to Trevor.  The links below cover what he shared in the audio so you do not have to take notes. https://stg.software trevorewen.com
undefined
Jul 13, 2021 • 24min

Trevor Ewen Part 3 - Functional Core Imperative Shell

The third of our series of discussion episodes with Trevor Ewen touches on a functional core and imperative shell.  This is an approach to building software that uses a strong core to extend to custom solutions.  We provide some options for building on your previous solutions in the modern world of software frameworks, libraries, and open-source. Functional Core The underlying theme in this approach is a functional core.  You want to craft a foundation that is solid and extensible to speed future development.  That does not mean maximizing code reuse as much as it does solution reuse. Instead, we focus on delivering a solution quickly and reliably with less worry about maintenance.  Thus, we can build quickly and worry about refining our solution for reuse after it has been delivered. As a result, we get speedy delivery, and eventually, we will see reuse where needed.  This process allows us to avoid designing code for reuse that is never used again. When To Share We wrap up this episode with a discussion about timing.  There is a level of "baking in" that is useful before converting code to a library or sharing it with diverse projects.  Yes, we can always design all code to be shared.  However, some solutions are too niche or customized to be useful outside of the original solution.  We want to find a reason to share code other than "because we can."  That means we need to keep an eye out for how often we see similar problems or use existing code snippets to jumpstart a solution. Great Links for more From Trevor https://stg.software trevorewen.com
undefined
Jul 6, 2021 • 22min

Trevor Ewen Part 1 - Building Software

We start a new season of episodes full of interviews in a discussion with Trevor Ewen.  Building software is an underlying theme of this part of our multi-part series of discussions with him.  This also includes the introduction to Trevor and a setup for part 2. A Little Background Trevor is an experienced software engineer, project manager, and real estate investor. He has overseen full-stack teams in clean energy, insurance, finance, and media. Notable engagements include Morgan Stanley, HBO, Bloomberg, Honest Buildings (now Procore), RunEnergy, Black Bear Energy, and PRco USA. He has an MBA from London Business School and Columbia Business School via the joint, global program. A Rich Environment For Building Software A key point to take away from this conversation is that building software can be done with more configuration and less construction.  The world is full of SAAS products that can get us to a solution quickly and reliably without breaking the bank.  These low-risk options may be exactly what you need to jumpstart your idea into a business or enterprise. The recent job market downturn has also forced many excellent developers to look for a new job or into consulting.  That can translate into finding resources to "rent" when you have a difficult hurdle to overcome or maybe long-term resources at a bit of a discount.  Of course, you never want to low-ball an employee, but you may find some deals out there. Great Links for more From Trevor https://stg.software trevorewen.com
undefined
Apr 23, 2021 • 14min

Object-Oriented Design : Invest In The Design Process

We wrap up the season with a focus on the design process.  There is a cost to doing this, as with most things of value.  However, you will find that the benefits in tighter, easier to maintain, and higher quality code are worth the investment.  We can use the tools and frameworks we have to take shortcuts to an object-oriented solution or be better by spending time on design. Object-Oriented Design Is A Revision We have discussed how the solution is always our primary focus.  Developers solve problems.  Therefore, our "why" is crafting a solution.  The emphasis is on the solution not on the craft.  Once we have a solution we are comfortable with, then we can look to mold it into something better.  Therein lies the rub.  We have a solution so we could push forward to implementation.  On the other hand, we can spend time refining the solution.  The wise developer chooses the latter approach. The Design Process Is An Investment There is no question that design time is an investment in our implementation.  A brute-force approach is often an option.  However, those solutions rarely hold up over time.  Even duct tape has its limits.  Thus, time spent on design assumes we will be able to make up that time in future endeavors to maintain, scale, or enhance our implementation.  That makes efficiency and clarity the primary goals for our design process.  We want to craft code that is worth re-use and that can handle relying on it for bigger and better things than this one solution. Stopping When Needed We also are going on hiatus for a while with the podcast.  This is going to be our last episode until further notice.  It does point to the value of making decisions and acting once a decision is made rather than some arbitrary time frame.  We often talk about goals and regular reviews of our plans.  However, sometimes it is best to act sooner rather than later.  That can help us avoid investing in things that we see of lesser value.
undefined
Apr 16, 2021 • 16min

Keep It Simple - Avoid Complex Object-Oriented Designs

Software developers are known for many traits.  Unfortunately, one of those is ignoring the keep it simple philosophy.  We tend to "show off" our prowess through complex designs and implementations.  However, those rarely are the best ones in terms of maintainability and even performance.  Simplicity has its benefits. Keep It Simple - Direct Is Better While there is a value in the "scenic route" when we are out for a leisurely drive, it is not the most effective way to travel.  The same concept applies to our designs and solutions.  The direct solution is often the best, even though it may sacrifice scalability or its ability to be applied in a general fashion.  When we focus on highlighting our design skills, we often end up with a solution looking for a problem.  That is not a mindset that servers our customers. Solve The Problem First Therefore, we should always start our design with a focus on the problem.  The starting point should be the solution and then map that to an object-oriented design.  If we focus on the OOD, we may inadvertently attempt to cram a square peg in a round hole.  This thought takes us back to the agile manifesto.  The number one goal of our solution should satisfy the customer.  While a solid design is valuable, it is a means to an end, not the end itself. Opportunity-Based Design When we start with a solution and then translate it to an object-oriented form, we are taking advantage of opportunities.  There are opportunities to improve our solution through OOD.  A good design makes use of these.  Thus, our solution dictates where OOD may be useful.  We can take advantage of those without using all of the features OOD provides us.  It is like many things in life.  Just because we can does not equate to "we should."  For example,  our car can go faster than the speed limit.  However, there are many cases and reasons not to push the car beyond that limit.
undefined
Apr 14, 2021 • 15min

Leverage Your Language - Use What It Gives You

An often overlooked facet of object-oriented design is how to leverage your language to speed development.  Every coding language has features and strengths to make your design or implementation better.  We should not design to a language initially.  However, we can tailor our implementation and detailed design to take advantage of these features. Leverage Your Language to Boost The Implementation Languages are implementation tools. Therefore, they come into play during that phase.  Nevertheless, you can leverage your language as you consider the details of the design.  Some approaches will either be simple or complex based on the language.  We can include the concept of interfaces or multiple-inheritance in a hierarchy.  That includes more granular steps like patterns built into the language.  We often see these in the form of iterators or factories. Keep Up With Changes While the initial design should leverage your language, enhancements and upgrades should incorporate the same.  Be aware of the changes to a language or environment over time.  That includes fixes, tweaks, and new versions.  A problem that may have been overly complex to solve in the past could be a "freebie" solution now that it is handled in a single line of code. Languages evolve and often do so with a focus on eliminating weaknesses.  That is due to developers suggesting features based on their pain points.  We often see a language that is limited in use during early versions become more general-purpose over time.  The developer is the customer, so the software team or company will cater to the developers.  The things that are difficult to use early on will be simplified or greater support provided. Under The Covers The changes to be aware of include those that are "under the covers."  These types of changes are much more implementation-impacting.  However, version upgrades have been known to make vast improvements in persistence, multi-threading, and thread-safety.
undefined
Apr 12, 2021 • 16min

Finding Balance In Your Object-Oriented Design Complexity

There are many areas of life where moderation is required.  Object-oriented design complexity is one of those situations.  We can create a solution that is highly granular and flexible or one that is monolithic and simple.  However, as is often the case, the best solutions find some middle ground that keeps our application flexible and limits complexity. A Balanced Object-Oriented Design Every solution is unique and has its own constraints and requirements.  Nevertheless, we have guidelines to avoid a solution that is either over-simplified or over-engineered.  They may appear obvious but are often overlooked. Isolate unique functionality - we will not get much re-use from it. Look for repeated actions or manipulations. Focus on a unit of work. Do not break down a problem that is not improved by doing so. When we walk through the steps of our solution, we should be either to easily see how to solve the related problems.  Those related problems are often a pointer to our methods and classes.  We want to break it down into easily solvable pieces and then stop.  There is no need for our object-oriented design complexity to rise to the level of micro-managing the solution. Re-use Is A Many Splendered Thing When we are thinking about code re-use and the related work to make a solution generic, there should be multiple uses.  This should be more than two occurrences or at least a vision of the code being reused many times.  That is where we gain back the extra time spent in creating a generic solution rather than brute force.  Our design should take into account that the direct and simple approach can also be the best.  We do not get points for an elegant solution in most cases. Simple First The best designs start with a simple solution.  It is easier to make our software more complex in a future iteration than simplifying it.  We also will have lower maintenance costs associated with a less complex solution.  These benefits add up and should bias us away from over-architected solutions.  Not only are there no gains inherent in a complex system, but there are also many assumed costs.  These include a slower solution, one that is harder to maintain, and a longer ramp-up time for new/additional resources.  Therefore, simple is better than complex when possible.
undefined
Apr 9, 2021 • 14min

Documentation Of Our Object-Oriented Solution

It is hard to think of a facet of software development that programmers dislike more than documentation.  This task is almost always pushed to the end, and shortcuts are used wherever possible.  However, we also are quick to complain about a lack of documentation when we pick up others' code.  Maybe we need to give so we can get.  that is the focus of this episode. Documentation Begins With A Signature All good documents start from an outline.  There is either a written or mental plan that the author follows.  In software, this objective comes from the signatures of the class and methods.   We have a set of details we must provide for every method out there. What are the parameters supported? Are there constraints for those parameters? What is returned? Are there exceptions or error-handling that needs to be documented? Do we require other classes or libraries? Are there side effects? That is a sizable list when you consider that many methods are documented in a sentence or two.  While documentation can be exact and concise, that is not always best. Using Documentation Generators Consider a method: integer DoSomething(parm1, parm2) Here is the typical documentation: DoSomething returns an error code or 0 on success. The first parameter is a number that tells which type of processing is needed (trim, pad, compress, encrypt). The second is a string that is processed. I am being a bit obtuse in the above comment, but not far from what most automated tools generate.  That should be a start for our documentation and not the final version. Add Color Commentary We need to add details and specifics to our documentation.  This includes things like validations, side effects, and avoiding magic numbers.  Therefore, a better approach to the above would be something like this. DoSomething returns a 0 for success, -1 if the action is invalid, -2 if the string is null, -3 if the action fails. The first parameter (parm1) is an integer with a value of 0 to 3. This tells the method the action to perform. 0 - trim the string 1 - pad the string (left pad spaces to make the length 20) 2 - compress the string 3 - encrypt the string The second parameter (parm2) is the string the action is performed on. The resulting string is set in the instance and can be viewed through the getValue method (provide a link to that method if possible). There is minimal formatting in the example above.  Nevertheless, notice how much more information we have now provided.  There is no guesswork, and our expectations are properly set.  Thus, we have a document that is useful and will make the next developer happy to work with our code.
undefined
Apr 7, 2021 • 15min

Test-Driven Development - A Better Object Oriented Design Approach

Testing and Design are often at opposite ends of the software development life-cycle.  However, test-driven development is an excellent way to drive our design.  It can help us build better classes and improve re-use.  This episode focuses on TDD and how it can point us to full-featured classes with better error handling and messages. Test-Driven Development For Design We previously looked at unit testing and class-level quality assurance.  While those are important tasks once we get the class implemented, they are better incorporated into the design process.  When we do, it ties our testing (validation) more directly to requirements.  Thus, we have goals for each bit of code to achieve.  We drive our implementation by the tests we need to pass.  This approach is not the only way to do so.  However, it does translate requirements to the implementation.  It also can help us find gaps. Testing Responses Testing centers around the responses and behaviors of our classes and methods.  Thus, our class must support a message, exception, or value that the test is looking for.  In the case of exceptions, I find testing a key indicator of where we need to support them or report errors.  That is because a unit test has this basic format. Make a call. Gather results. Compare results to a set of assumptions. That third step will highlight areas where we have the proper amount of error handling and messages supported. A Simple Example Let's consider a simple example to show how this works.  In our example, we have a method that takes two numbers, adds them, and returns the sum.  The requirements tell us we need to verify the sum is correct; we warn the user if a negative value is sent.  Finally, we need to warn the user if they do not provide a number.  If we implement first and then test, we can easily forget the latter requirements.  We will probably add the numbers and return the sum.  It is not until we get to testing that we will realize we have some exceptions handle.  If we take the test-driven development approach, then handling these exceptions and related messages will be in our minds from the start.  That can heavily influence the kinds of things we want to support and return as we design our class.
undefined
Apr 5, 2021 • 14min

Testing Object-Oriented Code - A Better Design Approach

We have spent a lot of time on the core concepts of object-oriented design and programming.  However, testing object-oriented code is at least as essential to our practical approach.  We need to ensure that our code is written with a quality that makes it worth re-using.  Otherwise, it is a better use of time to write new code instead of wrangle low-quality code with the idea of re-use.  We have all seen these situations where it is easier and faster to start from scratch than building on previously written code. Testing Object-Oriented Code Through Design We will focus on test-driven development in the next episode.  However, our implementation and approach to a solution can be improved with the inclusion of unit tests.  There is a level of expectation that unit tests point to.  When we start to code these, the gaps in our return values and messages become apparent.  Thus, we get the benefits of tested code and a more thorough design. Unit and Class-Level Testing Unit-testing typically is at the method level.  The good news is that we can connect a few of these and easily shift to class-level tests.  These are important steps towards building a highly re-usable class.  We will show (through successful tests) that our methods work individually and as part of the class system.  While interactions and interfaces for our class are important, it is more valuable to have a class that is a solid ecosystem. The Goal Is Re-Usable All of these points lead us to how confident we are in our code.  If we have a low-confidence, then why would we re-use it?  In those cases, we are better off writing "one-off" code that avoids the costs of object-oriented.  There is no benefit in staying on the fence.  Either embrace OOD and testing object-oriented code for re-use or write something quick-and-dirty.  This concept applies throughout the real world.  There is no sense building on a flimsy foundation.

The AI-powered Podcast Player

Save insights by tapping your headphones, chat with episodes, discover the best highlights - and more!
App store bannerPlay store banner
Get the app