Showing posts with label software management. Show all posts
Showing posts with label software management. Show all posts

Wednesday, July 30, 2025

Design versus Architecture in software development

First try (from Gemini 2.5 Flash)

Software architecture defines the system's fundamental structure, outlining its major components, their high-level relationships, and the overarching principles and quality attributes (like scalability or security) that guide its construction. It's the "what" and "why" of the system's foundational choices, which are costly to change.

In contrast, software design focuses on the detailed internal workings of individual components and modules, specifying their logic, data structures, and algorithms to implement the architectural vision effectively. It's the "how" of putting those foundational pieces together, generally with a lower cost of modification.

Second try (with my input)

Software architecture defines the system's fundamental structure, outlining its major components, their high-level relationships, and the overarching principles and quality attributes (like scalability or security) that guide its construction. It's the "what" and "why" of the system's foundational choices, which are costly to change and, by their nature, represent the unique, large-scale blueprint of a specific system, and are not directly composable with other architectures.

In contrast, software design focuses on the detailed internal workings of individual components and modules, specifying their logic, data structures, and algorithms to implement the architectural vision effectively. It's the "how" of putting those foundational pieces together, with decisions often leading to reusable and composable solutions that can be combined to build larger features or even integrated into different systems.

Why the difference (Gemini):

My answer was a reflection of common knowledge, while your insight stemmed from highly specialized and deep expertise in higher-order functional programming.

Some remarks:

  • Architecture is often brought in from external sources, less often developed.
  • Architecture is an expensive risk: a bad architecture can doom a project, a poor architecture can explode your costs.
  • A team that does not master their architecture and designs is a big risk, and not all teams have the skills needed for chosen architectures and designs.
  • Design fits in an agile process. Architecture is often hard to fit in an agile process.

All original content copyright James Litsios, 2025.

Sunday, September 24, 2023

Thinking about skills in people and in software

Here is a handy way categorize levels of software sophistication:

  1. Software implements features
  2. Software  supports software that implements features
  3. Software supports software to support software that implements features
Here is handy way to categorize levels of people skills:
  1. Person implements features
  2. Person supports people that implement features
  3. Person support people that support people that implement features
Let us combine some of these people skills and levels of software sophistication:
  1. Person implements software that implements features
  2. Person implements software that supports software that implements features
  3. Person supports people that implement software that implement features
  4. Person implements software that support people that implement software that implement features
  5. Person support people that support people that implement software that implement features
  6. ...
Note how entry 4 is a hybrid of people skills and software expertise!

The above lists actually makes sense, yet they are too simple. We can do better!

We can distinguish between support as:
  • Direct support
  • Proactive support
For example:
  • A unit test is software that directly supports software.
  • A library or a framework is software that proactively supports software.
More examples:
  • A project manager directly support members of a project with a plan.
  • A servant leader proactively support his or her team members.
We can bring this together as:
  1. Person implements software that implements features
  2. Person implements software that directly supports software that implements features
  3. Person implements software that proactively supports software that implements features
  4. Person directly supports people that implement software that implement features
  5. Person proactively supports people that implement software that implement features
  6. Person implements software that directly support people that implement software that implement features
  7. Person implements software that proactively support people that implement software that implement features
  8. Person directly supports people that directly supports people that implement software that implement features
  9. Person directly supports people that proactively supports people that implement software that implement features
  10. Person proactively support people that directly supports people that implement software that implement features
  11. Person proactively supports people that proactively supports people that implement software that implement features
  12. ...
You might be thinking: this stops making sense!
Not so! Each of these categories are different, and imply different levels of skills and experience. Some need more people skills, while some need more software skills. 

Wrapping this up: Yes, it makes little sense to enumerate these categories. However, it makes total sense to understand them, and understand how the micro-structures of software and teamwork combine in different ways and demand different levels of experience and skills. 

Wishing you continued success with your project!

 All original content copyright James Litsios, 2023.

Sunday, August 16, 2020

25'000 views; Some topics I am passionate about

 This week a took a day off to walk in the alps with my son. And while doing so noticed that my blog view count was 24999. So I quickly asked my son to be the next view! 

My blog has been around for more than ten years, and a tenth of a second is all a site like Google would need to achieve the same hit count. Still, I write this infrequent blog because it helps me find what is relevant to me and to others, and helps me communicate better. And encourages me to do my best, because I do care about my audience.

I write infrequently mostly because I do not have the time. Also, my topics tend to be complex, and sometimes even sensitive, and therefor take time. Still, I often jot down a title, sometimes with a page or two of content. These then become public if I happen to have free evening or weekend. For example, these are my unpublished blog titles going back to early 2019:

  • Balancing productivity, tempo, and success
  • Program = complementary
  • Some retrospectives in business of innovation
  • Type centric vs ...
  • The instantaneous view of the real world has no math
  • Control and flow in innovation
  • Lessoned learned: writing "coherent software"
  • Careful Software Architecture (in Python)
  • Absent minded at work
  • Choose your inner truth: run your organization like a hedge fund
  • Dealing with time
  • Computer languages as data for machine learning
  • My reality? Or your reality?
  • The Peter principle in software development
  • Innovate, but don't waste you time
  • ...
Out of these, you might notice topics that I am passionate about:
  • Innovation
  • Productivity
  • Formal software and architecture
  • Teamwork and organization processes
  • Modelling the real (and unreal!) world
The thing is: You cannot innovate if you are not productive. You cannot be productive if your teams and organizations do not work well together. You cannot work well together if you do not understand how to express the real world in your work, and to be precise and correct when needed. These are topics that I care about, and what this blog has mostly been about.

Cheers to all, I am looking forward to sharing some more writing!


Sunday, April 12, 2020

Thinking versus brute force "doing" in software design in 2020

About thinking versus doing

(I put a subset of this on YouTube as: https://www.youtube.com/watch?v=_kXpyctbmrQ)

Is it ok to program by "brute force" and put aside your brain?

A few years ago, I wrote on the pros and cons of programming with explicit and implicit type declarations. In 2020, I feel that this question is almost irrelevant. Therefore to ask the question:
Should we think about software design when we program? 
There is a trend in software development which states "developing software products is not about thinking but about doing".  I know many venture people who believe very much in this statement. Yet the reality is that software is a process of thinking (in part at least). Still, from a pure seed-venture-money game, the rule of "it is not about thinking" is true"! Because the number one rule is "be fast" and thinking too much will very much slow you down.

Is it then both true and untrue, that we should both use and not use our brains when we write software? Yes, and yes! And it is exactly this subtle challenge that makes software management in innovation a tricky game.

Thinking can be done different ways, different approaches can be taken. Some are efficient, some are a waste of time. Some will help your software grow, others will block you. Some will help you meet your deadline, others will invariably lead to failure. The game is then only to think in the ways that help you!

Some of my colleagues have heard me condense these concepts into one statement:
It is about thinking backwards!
There are many ways to do this. I will cover just a few here, there are in fact as many more.

Play to win above all else

In recent blitz chess games, FM Lefong Hua repeats "it is not about calculating the end's win game", (because that is not a guarantee win), instead is about about "flagging your opponent". By which he means, winning is not about thinking within the classical rules of chess, it is about meeting the "win conditions", which in blitz chess games is much about not running out of time (being flagged).

Transposed into a software development, that means it is not about meeting the classical rules of software design, it is about thinking through how to always meet your goals and deliver results. Or to be more specific, it is about thinking backward, to find a path back from your "runnable software" goals, to your current status that guarantees your development success.

The heart of your software comes first

I have mentioned that "One of the little understood properties of programming is that at the lowest level things tend to be single dimensional".  A good software design builds a "break" or "separation" in that unique dimension "just about where your main product abstraction is", to achieve a sandwich like design where new product abstractions are added "by reassembly" of the two separated parts.

There are few ways to do this, domain specific languages (DSL) and functional programming (FP) being my favoured approaches.  While all my major software developments had DSLs, it was only much later in my career that I understood that what was working for me was not the DSLs but the effort to maintain separation between interpreter and interpreted abstractions. This separation is naturally achieved with a DSL, yet can also be achieved with adjunctive higher order FP. (The "ultimate tool" is then to combine the two concepts as adjunctive FP based DSLs, which was the base of Elevence's contract language).

Be functional and agile

Agile development is a lot about prioritizing your requirements and implementing them in work iterations. That means that the first level of your design, what might be seen as the first draft of primary keys of your data base, are directly tied to the most important business concept (taken from OO vs FP vs agile). The trick is then not to see this as a database of data, where keys are data, but a database of code, where keys are functional properties such as APIs with specific invariants (e.g. somewhat like class types in Haskell). The extended trick is then also to make this a normalized design (just like a normalized classical DB schema, but in a the "functional space"), for example by using linear types.


Brute force yes, but with the right pieces

Let us put this all together, our first conclusion is when building new software:
Use brute force and minimal brains to assemble data and call external APIs 
Importantly, keep your program structure as flat as possible when you do this. Which pretty much means to shun OO patterns, and to use as many array and container like constructions as you want.

Then, and this is the tricky part:
Incrementally invest effort to separate interpreter and interpreted abstractions in your code.
Always make sure that these abstractions fit within the plan to your deliverables. That means you are able to think backwards from your deliverable goal, and work out the path to your current development state, the path which you will follow to build your code. An agile process and a good team will make this an easier job. Also, all those arrays and containers will need to fit into a single unified concept (e.g. such as indexed tensors).

It's complicated

Sometimes things are just too complicated. Many developers do not know how to "separate interpreter and interpreted abstractions".  Here I will be honest, it is not easy. And just to make this clear, the last DSL I wrote took me multiple tries until "I got it right".  Also, to mention that embedding product abstraction in higher order FP is even harder than writing DSLs.

Worse, the process is "hack brute force" to assemble data and use external APIs, and only then think about how you can slice your interpretive abstractions. These means that initially, software development is about doing, not thinking. Tricky...

Welcome to 2020

I have been writing this blog for almost 15 years. Interestingly, a major change over these years is that there is so much well integrated open source software (OSS) out there that it is cheaper to "just try" than to "think" (when using OSS and third party APIs). And in part it was this reality that led me to write this blog today. Enjoy, and stay safe!

All original content copyright James Litsios, 2020.

Sunday, October 27, 2013

What does the US government teach us about managing software projects?

Most of us have probably worked all night and all weekend sessions in order to finish a project "on time". And we all know that is the sign of "bad management", and can also be the sign of an impossible task. Therefore, looking back at the US government working hard a few days before the deadline to get the debt ceiling raised, can be seen as a sign that the US government is badly managed, but can also be seen as a sign that it had an something impossible to do.

You might say, a government and politicians is not the same as a software development organization. Governments are fragmented, many politicians only have a job because of these differences of opinions, politicians are continuously trying to shift blame, etc. While the goal of all members of a software development team is to finish a project on time and be successful.  Or is it?...Hmmm...  In fact, that is not always clear!

The tricky nature of people, is that if they do not feel enough belonging into a  common cause, they can very easily switch to supporting its "anti-cause". Politicians know this, and much "political noise" is the game of making sure that not everyone agrees with your oponents. A development team can suffer much damage when not everybody is just "happy" to work towards the common goal of finishing the project on time. This "bad behavior" is often subconscious, yet can also be a very conscious feeling, and even sometimes an open secret, referred to, for example, with flippant remarks. What happens is that dissension can feed upon itself and simply suck away much precious work time. The team may recover under the stress of the approaching deadline, but often that pressure simply comes in too late.

Luckily, difficulties in managing teams is not new, and good guidelines exist. The first recommendation is to use an agile process:
  • The "short" duration of the each iterative step ensures an optimal common focus driven by the "stress" of the deadline. And by the way, that is how you decide how long your agile iterations should be: short for a less mature team, longer for a more mature team. 
  • The independence of product management (e.g. product owner role in scrum), ensures that no dissension exists in the business goals presented to the team.
  • Roles like the scrum master, help focus on value to all, above the value of individuals.
Yet the agile process does not keep dissension happening on "long term" concepts. For example, on design and architecture, or product goals. Usually, technical dissensions are more problematic than business dissensions. The question is often: "How to make sure that people work together productively on long term technical goals"?

My answer is:
Get every one to agree that common long term technical goals exist only to constrain the team; New concepts can be brought in by the team's individuals, but only within the short term "iterative" process. 

For many, the idea of only be able to bring in new concepts within a short time frame is just not acceptable. They argue: we need more time! But too much time would mean too much uncertainty, and uncertainty is an area in which dissension can strive. Another argument is that vital new concepts will never be brought in if there is no long term goal, and as a result the team may fail. This is true. But the consequence is that people need slack time: unmanaged time outside the process in which they can mature new ideas (see delivery focus versus creative slack). It is only when ideas and new concepts have matured that an attempt can be made to bring them in to a project within a solution. And the criteria of maturity is "needs to be able to deliver within the short term iterative part of your agile process".

People may still argue that a bleak constraining, almost pesimistic, long term technical vision does not provide value, is "no fun", and possibly even not worth working for! These are not unreasonable worries.  Yet these remarks are all based on experiences where short term efforts fail to provide enough value, or fail to provide enough satisfaction.They are also come out of cultures that do not understand the critical need of a "side" process in which ideas and techniques are selected, grown, and matured, until either they are rejected or they are brought into production.

US politics, like most political systems, have this concept of the parallel process that prepares material before bringing it into the short term process of getting decisions made.This is a system of influence, of key players, committees and lobbyists. It would be wrong to deny that development organization are not subject to similar games of power, yet the big difference is that a development organization should only get one source of funding (from business). While a democratic system gets multiple sources of funding with often contradicting goals.

I cannot make this posting too long, therefore to summarize:
  • Run a tight development process: only bring in ideas that are mature enough to succeed withing your "short term" production cycles.
  • Encourage independent new long term ideas but outside your production process: Accept that there is some political process in how your team brings in new ideas into their production effort; Make sure that new concepts are mature enough that they can be brought into production with good certainty, within the normal "short term" development cycles.
  • Encourage "constraining" long term team goals within your production process: It is OK to debate as a team on longer terms plans that simplify things and restrict usage of new technology. I say this because technical entropy, the fact that things "grow more complicated with time" will kill you if you do stay united as a team to fight it.
  • Make sure that your team has enough slack time: And make sure also that they have the culture to use it wisely, for the benefit of the project (and not for each developer's ego).
  • Have only one external driver per development team: The same for "normal" short term development process as for the long term "creative process". This will keep the "political" debate healthy. And that is again a reason why agile processes have only one business representative per team.
  • Drive software with deliverable features, business with revenue streams: It is this separation and its "double layering" within the overall development process (e.g. agile development teams versus one product management team) that keeps the political "game" sane! Technology does not generate money, only features do! (Well, within a bigger model it can, but that is why you might consider having a CTO outside the development team process).
 This brings us back to US politics: they are like a very, very, bad development team. They apply none of the "good behaviors" above. Not a very good role model for their fellow citizens!

All original content copyright James Litsios, 2013.


Monday, September 17, 2012

From old to new: dealing with legacy software

A tricky problem is to deal with software legacy.
I think I have never been anywhere where I did not need to deal with legacy some way or another. In fact my first task on my first job was to improve the performance of "old" design rule checker (DRC) by upgrading its geometric store with a KD-tree. That was during a summer job, and later as employee, I was asked to write a new DRC to replace the old one. (A DRC is used to check geometric rules in layouts of integrated circuits). The new DRC was better than the old one, and part of an automated layout tool for analog circuit, which... ultimatly failed. Commercially the project did break even, but other systems worked better. Looking back, with the hindsight of knowing which system succeeded, this CAD sytem failed to approach the problem the right way, which was incrementaly. For example, the requirements for the DRC were: do what the old software does but better and faster, yet they really should have been "make it incremental": a small change in the input should generate only moderate of work to revalidate the rules.

Legacy is about dealing with code that exists already and that causes you trouble. Typically the trouble is that the legacy software is equivalent to a massive traffic jam where it is no longer economic to work on it. Changes to the software are simply too expensive: they take too long and they are risky. Unlike new software, legacy software is already in use, and this simple fact is the root of all problems: it makes you stupid!  Take the example of that DRC project, my boss had said “do what the old software does but better and faster”,  I wrote a great boolean operations on large geometric figures package; It was fast, it was better than the previous package, but… it was not what was needed!  This is what I call  the “dumbifying” effect of legacy software, and the subject of this post.

When a magician performs a trick, you may know the magician is tricking you but mostly unable to do anything than to “fall for it” and think it looks real. Legacy software is a little bit like a nasty magician, it makes things look more real than they deserve. So for example, if your team tells you they can rewrite a legacy system, your tendency will be to believe them, just because the legacy system exists already and this somehow makes you more confident. If you are given analysis of the legacy system and it is incomplete, you will judge it less harshly than analysis for new yet to be written system. If your team tells you they can only test 10% of the features of your legacy system, you might say that is better than nothing, while a proposal to test “only” 10% coverage of a new system would be treated as a joke.   Legacy software is a little bit like a con artist! It puts down your guards and corrupts your sense of proportion. Worse than that, legacy software makes you feel bad when you think of some of its “legacy properties”, the result is like a Jedi mind shield, legacy software actually blocks you from thinking clearly by making you suffer when you look at it "truthfully "!

In a former job, as a development manager, I was continuously saying “no”, “no”, “no”… to the same question which was “can we rewrite it”. The thing is that rewriting legacy software when you have not yet accepted to look at it “truthfully” is often not going to work. So here are my recommendation on how approach you legacy software:
  • Never believe you can rewrite legacy software from scratch without keeping something. Maybe you are keeping a protocol, maybe you are keeping the business functionalities, maybe you are keeping the algorithm, but you need to keep something.
  • Keep what is most precious in your legacy software. Again, it might be the protocol, the business functionalities, .. but as you need to keep something (see above) you want to make sure that you keep what is most valuable. The more the better!
  • Make sure to deeply analyze what you have identified as valuable and that you want to keep in the legacy software. Analyze it to death, until it hurts!  That is because by default, you will shy away from doing this analysis, and that will cost you!  This is the really the number one rule with legacy software: do not let “it” convince you that you do not need to analyze what you will keep! (See dumbifying and con artist remark above).
  • Also, bring in new resources to provide fresh views on your legacy analysis. Again, by default the legacy will bias you, bring in someone that can look you problem and solution without prior experience with the legacy software.
Sometimes what you want to keep is deeply imbedded into your legacy software, for example as an implied data model or API. Do not hesitate to use “tricks” to extract it out at the lowest cost. For example you can extend your types to produce a trace info with each operation, to then analyze the trace files extract an implied structure.
Once I wanted to extract an implied model in C++, so I wrote a “hand crafted” C++ parser. It took about three days, I started with an equivalent yacc and lex and the first C++ file to parse, and proceeded to write the parser to parse exactly what I needed in the first file, extending the parser by running the parser over and over, line after line. When I got to the second file, I was already moving by a few lines at a time with each iteration, and by the end of the effort I had parsed the 50 or so files that had the data I needed.
Finally, do not forget the business: if you are in it to make a profit, never write code unless it is supporting your business strategy. This is probably the hardest part with legacy software: your business and marketing people usually have no idea how to approach your legacy rework. If you not careful your development will effectively hijack your legacy strategy and possibly lead you into business oblivion.