I have recently graduated from university and started work as a programmer. I don't find it that hard to solve "technical" issues or do debugging with things that I would say have 1 solution.

But there seems to be a class of problems that don't have one obvious solution -- things like software architecture. These things befuddle me and cause me great distress.

I spend hours and hours trying to decide how to "architect" my programs and systems. For example - do I split this logic up into 1 or 2 classes, how do I name the classes, should I make this private or public, etc. These kinds of questions take up so much of my time, and it greatly frustrates me. I just want to create the program - architecture be damned.

How can I get through the architecture phase more quickly and onto the coding and debugging phase which I enjoy?

  • 61
    By doing a lot more of it. You'll figure out what does and doesn't work. Notice that asking the question here is following the same trend of discussion without the context of actual code: time that could be spent learning by doing. Debating this stuff is fun, and certain patterns are objectively better than other ones, but it's really really hard to have a meaningful opinion without experience (read: scars). Commented Jan 3, 2019 at 1:50
  • 5
    Architecting is your planning phase - get it right and it's 90% of your effort, with the rest being the coding, debugging and user acceptance. Skipping it or rushing it is not recommended, as you can end up with unmaintainable, unextendable solutions, so if you don't like doing it then you probably need someone else doing it for you... Naming is one of the hardest issues in software development, a developer can agonise for days over the name of a 5 line method. Make everything private until it needs to be something else. Split classes up when they do more than one thing.
    – Moo
    Commented Jan 3, 2019 at 6:15
  • 5
    in the case of OOP, you can start by understanding and using the SOLID principles. It should help answering some of your questions (such as whether this should be private or public, splitting or not splitting some logic...) by giving you a reasonning behind the decisions you make.
    – njzk2
    Commented Jan 3, 2019 at 6:56
  • 8
    I feel the question is not as good as its score suggests. The question lacks a lot of context. It also says something about how programming is (perhaps) mis-taught. Computer Science should not be taught in a way that begineers are paralyzed to code. Commented Jan 3, 2019 at 9:45
  • 3
    "Weeks of coding can save you hours of planning."
    – user244218
    Commented Jan 3, 2019 at 14:50

13 Answers 13


Perfect is the enemy of good.

That said, you should not cut corners. Software design will have longer lasting impact, and save you (and your peers) tons of time and effort in the future. It will take longer to get right. Most of the time spent programming isn't hammering on a keyboard, but by a whiteboard figuring out how to solve a problem.

But you also shouldn't worry about perfection. If two designs fight to a stalemate, it means they're likely about the same goodness. Just go with one. It's not as though you can't change things once you figure out the flaws in that design.

(And hopefully it will also help out once you find out that there's not just one way to debug/solve technical issues.)

  • 25
    Paralysis by Analysis also comes to mind.
    – mike65535
    Commented Jan 3, 2019 at 0:42
  • 7
    Sometimes the perfect final arbiter for a design decision is a quarter. Commented Jan 3, 2019 at 5:55
  • 11
    YAGNI and KISS and GTFO ;)
    – JollyJoker
    Commented Jan 3, 2019 at 9:30
  • 10
    To anyone reading this answer - For the love of god don't use "Perfect is the enemy of good" to justify lackluster implementations. The intention of this saying is to prevent you from overengineering, not to slack off and create some sort of poorly designed mess like Windows Vista or the Apple III.
    – T. Sar
    Commented Jan 3, 2019 at 15:35
  • @T.Sar: the failure of Vista was virtually 0% technical failures and about 100% MBA failures. Commented Jan 3, 2019 at 17:44

For simple and small programs (e.g. with fewer than ten thousands lines of source code), you can architect them while writing the code. If you adopt an iterative and incremental development approach, you'll progressively make architectural decisions along the way: so write a few dozen lines of code (adding some single micro feature), improve them until no warnings return from your compiler, test that in your debugger, and repeat.

do I split this logic up into 1 or 2 classes, how do I name the classes, should I make this private or public, etc. These kinds of questions take up so much of my time

They should not. And they don't matter that much for a small program (because small, simple programs are easier to improve, e.g. to change names, etc...). You just need to be consistent and prioritize the readability of your source code. You may find the need, from time to time, to slightly refactor some small parts of your program (and that is not a big deal).

Compare this to many free software projects (even big ones like the Linux kernel). The developers did not spend significant effort "architecting" in the early stages. UML is almost never used in free software. Additionally, you'll learn quite a bit by studying the source code of several free software projects.

As a newbie, you will either work on a large software project in a team, where you can simply trust the senior developer (who makes architectural decisions), or you'll work alone on small projects (typically, fewer than a few dozen thousands lines of source code). In the latter case, you'll make incremental architectural decisions, refactoring your application from time to time, after which the "architectural design" will evolve naturally.

How can I more quickly get through the architecture phase and onto the coding and debugging phase, which I enjoy?

For small software projects, which take less than a year of work, very easily: don't do architecture. Spend perhaps half an hour brainstorming on the overall design. Then start writing code, with an iterative and incremental development approach: write a few dozen lines, compile it (with all warnings and debug info enabled, e.g. g++ -Wall -Wextra -g with GCC for C++) until you get no warnings (and pass it in some simple static source code analyzer, if you have one, e.g. clang-analyzer), test that code with a debugger, commit it to your version control (e.g. git), rinse and repeat. However, be sure to avoid technical debt: when something smells bad, do work (by refactoring and reimplementing) to improve it.

On the other hand, in a team environment, the architecture work entails the initial discussion to define every team member's responsibility. That discussion is led by the senior developer (who is not a newbie). Read about agile software development and The Mythical Man-Month.

I just want to create the program, the architecture be dammed.

Excellent intuition (at least for small projects). So think a few minutes about your program, and start coding it with an iterative and incremental development approach: code a few dozen lines and make sure they work well, then repeat. Before that, study the source code (and observe the architecture) of similar free software projects and more generally do some bibliographical work and research.

In some cases, think about a metaprogramming approach: there are situations where you would like to generate some "source file" (examples include using parser generators like bison, glue code generators like SWIG, Google protobuf, and sometimes you might want to write a simple script -or use a generic preprocessor like GPP- to emit some of your C++ or Java code to avoid repetitive coding).

PS. I am a research engineer, have a PhD in computer science and 40 years of experience, and I never did "architecture" like your question suggests, while having worked successfully on several medium sized projects, and a few big ones (the GCC compiler itself). For me "architecture" is just the planning phase of the work of the next few days or weeks (and I usually do that while dreaming or sleeping and certainly without any computer, and usually without even a pencil). Also, when writing research grants, I am somehow and incompletely designing an architecture.

NB: some software projects need a lot more architecture than others. For example, if you write the control system of an artificial heart, or of a neurosurgery robot, you won't work in the same way as when writing the average mobile-phone application. See also Norvig's Teach yourself programming in ten years page.

  • 1
    That's how it usually comes to me as well. I give sufficient amount of time before starting the program, and by the time I start, I'll have several clear ideas on how I want to structure it, and I didn't actually make a point to sit down and think about it. It sort of just flows naturally to someone who tackles such issues regularly.
    – Neil
    Commented Jan 3, 2019 at 7:52
  • 1
    Considering the source code of GCC, completely organic growth is typically not something that people from the future will be thankful of. Most GCC contributions I've seen are particularly egregious cases of "make my thing work and get out of here as fast as possible" because the rest is already like that.
    – Kafein
    Commented Jan 3, 2019 at 14:17
  • 1
    My claim is that every large enough code base grows organically (see Gall's law...). Also, it would be completely foolish to handle the architecture of a huge software project to a newbie Commented Jan 3, 2019 at 14:18
  • I'm on a team that's somewhere between the two sizes you described in the first half of your answer. Our project is more than ten thousand lines long, but it isn't large enough to require more than about half a dozen developers working full-time on it. We're in a position where we're big enough to need to carefully plan our architecture, yet small enough that all of us need to be able to make architectural decisions ourselves. Your advice to either grow organically or ask a senior developer wouldn't work for my team specifically. (But I guess my situation is probably a little uncommon, too.)
    – Kevin
    Commented Jan 3, 2019 at 17:33

There are three mottos I like to keep in mind.

  • "Everything Should Be Made as Simple as Possible, But Not Simpler"

    To take your example of "one class or two?", I'd ask, "which is the simpler solution?"

  • "No obvious bugs" versus "Obviously no bugs"

    The latter is preferable!

    And that's the reason why it needs to be simple, i.e. so you can reason about it. One big class might be (or it might become) too big and too complicated to reason about, in which case you split it into several smaller classes, where you can say "Each class is small and does what it says it will do -- and their interfaces are simple, and they combine in the right way."

    1. The code should run in theory (i.e. in your head).
    2. Then if it doesn't work in practice you can debug it until the practice matches the theory.

    A novice sometimes doesn't bother with step 1 though, i.e. running it in your head (e.g. because it's too complicated) -- but in that case it's only running "by accident" rather than "in theory", possibly because you haven't tested it enough to find non-obvious bugs.

  • Gall's law

    This is a.k.a. "refactor".

    In practice this means:

    1. Start with a[ny] simple system that works
    2. Now it's time to add a new feature
    3. Refactor the existing system so that (i.e. until) the new feature is easy to add
    4. Add the new feature

    5. ... and repeat as above

    This matches mottos like YAGNI i.e. don't refactor (worry about architecture) before you need to ... but create the right architecture just in time i.e. when you need it for some specific purpose.


What you can do is start with the minimal number of abstractions that you need. For example, a Person class in one file. Now as you keep on adding code and features, you start seeing things that need to be moved to a different abstraction. For example the single responsibility principle(S of SOLID) tells you to not have methods related to address parsing in the Person class. So you now know that you need an Address class.

But it is always good to take some time to think about what "minimal number of abstractions" looks like for your system. Start from a good enough architecture and improve it as you go.

edit: @Basile answer gives an example on how you can iterate and improve on your minimal architecture.

  • 4
    I disagree. Trying to use minimal number of abstractions shouldn't be the goal. Building up a viable structure on the long-term is what is more important. Don't just think ahead the minimum necessary time, but think about building the code so that others can handle it too in the far future. If abstractions make the code more readable and workable, it's a clear improvement to it. I'd rather advise to write reusable, modular code. That said, it's a matter of experience to be able judge that.
    – Battle
    Commented Jan 3, 2019 at 7:07
  • @Battle Your point is that future-proofing is equally important, am I right? I would agree with this, though I suppose the ideal would be to create a program with the minimal number of abstractions also taking into consideration future development. I would argue that an arbitrary abstraction with no benefit in the now and in the future is only making your program worse, not better.
    – Neil
    Commented Jan 3, 2019 at 7:13
  • 2
    In real world you would have a lot of context around the usage of the software so your minimal architecture would cover a lot of the currently known use cases. I think that gives you a decent starting point. Modularity and reusability are non-functional requirements most of the time. Should they come in the way, its ok to ignore and hammer away on your keyboard. But yes, minimum abstraction should not be the final goal. But it could very well be a starting point.
    – sul4bh
    Commented Jan 3, 2019 at 7:26
  • @Neil - Yes, I was talking about future-proofing, and I think it has to do with structuring the code and with abstractions as a part of it. But I wasn't talking about arbitrary abstractions, but about the goal to minimize them, as if they'd be something inherently bad. They are bad when they are done bad.
    – Battle
    Commented Jan 3, 2019 at 7:28
  • 3
    @Battle: adding structure beforehand "just in case" is what easily leads to overengineering. To my experience, just having always the number of abstractions which are required for the current size of the code base" is a really good goal - no less, no more. Abstractions should be added when the code base grows, not beforehand. That is how I read this answer. But maybe the wording "minimal number of abstractions" can be misinterpreted.
    – Doc Brown
    Commented Jan 3, 2019 at 8:16

Time spent thinking of the architecture of a system is not time wasted.

I believe your question could be rephrased as "how can I be more efficient with taking architectural decisions?".

My short answer to that would be: you need to discover the core principles that will allow you to reliably and efficiently take decisions and then you need to actually go out and shape a real-world piece of software. This will be a long journey of seeking out knowledge, trial and error and personal development.


And for a longer answer...

I should first clarify the concepts: I use the word architecture to describe the structure of a complex software system when I am working with processes, services, APIs and databases. I use the word design to describe the structure of only one piece out of a more complex system, when I am working with classes, functions and libraries. These are my definitions, some people have different definitions. But in this context, I believe you are talking about design.

I think there are 3 important things to keep in mind when discussing this topic:

  • architecture and design exist without them being explicitly described via diagrams or documentation, also without them being maintained by a team or a person (an architect). Any system has an intrinsic architecture and an intrinsic design that can be described post-fact.

  • software development is not programming, it is programming over time. I am making this distinction because I think it is one of the biggest blind spots for people coming in the industry (myself included, at one point in time). What this means is that, compared to university projects or personal side projects, working on a real-world software system is exponentially more complex, because any architectural decision will have a big impact on the development of the system, with time. Your decisions now will come back to haunt you, guaranteed.

  • because architecture and design exist instrinsically and because the code base is a living thing that evolves with time, architecture and design also need to evolve. They will either evolve in a controlled manner through conscious decisions taken at the corect time, or they will evolve chaotically, driven by the coding. This is crucial to understand, because it means the traditional approach of "architect first and write code second" is flawed. Of course, when starting a project from scratch, some architectural and design work needs to be done up-front. But other than that, there will be a lot of architectural and design decisions still to make while developing the system.

To distill the above further, it is very important to be aware of the fact that you will be making design decisions while writing code, either consciously or not. You should strive towards making as much of those decisions consciously and critically, as any decision taken lightly can have a big impact on future work (this impact usually manifests itself in the code base becoming very difficult to change for fixing bugs or implementing features). Robert C. Martin illustrates this beautifully, with data, in his book "Clean Architecture" (which I highly recommend by the way).

So, now that we know why architecture and design are important, what are the core principles that can give us a proper framework for good decision making? I had this question earlier in my career, I felt like there is something missing in my toolset but didn't know what, didn't know how to describe it or go looking for it. I will share some of these principles that I discovered with time and I hope they will make your life slightly easier:

  • a set of very simple but powerful coding tricks can be picked up by reading Martin Fowler's book "Refactoring: Improving the Design of Existing Code". There are too many to list here, but these are very low-level, coding-time decisions you can make to vastly improve your code structure and help you take the design decisions. The book also makes a good case for integrating unit testing into your personal workflow and how to write testable code.

  • specifically for OOP, you should look at the SOLID principles. They are a bit abstract and difficult to wrap your mind around at first, but very powerful. I suggest you start with the first 2 to get the most benefit quickly:

Single responsibility principle: a class should have only a single responsibility (i.e. only changes to one part of the software's specification should be able to affect the specification of the class).

Open/closed principle: "software entities … should be open for extension, but closed for modification."

  • the concept of composition over inheritance

    the principle that classes should achieve polymorphic behavior and code reuse by their composition (by containing instances of other classes that implement the desired functionality) rather than inheritance from a base or parent class.

  • the concepts of coupling ("the degree of interdependence between software modules") and cohesion ("the degree to which the elements inside a module belong together.")
  • the DRY (Don't Repeat Yourself) concept
  • the command/query separation concept (" every method should either be a command that performs an action, or a query that returns data to the caller, but not both")
  • the concept of stateful versus stateless system (my rule of thumb is: avoid handling state; build stateless systems as much as possible).

Of course, these are just concepts, not rules. The first step is understanding them and being aware of them. Next comes actually using them in practice and building experience on when you should follow them and when you should not. And then there is a continuous process of refining your understanding of these concepts, their negative sides and their complex interactions with each other.

I think the most valuable advice I can give you is: have patience with yourself. You just started down a long but fulfilling road. Keep practicing and experimenting, take note of what works and what doesn't and you will only get better with time.

  • This is something one must learn with experience. It's half your job, and doing it badly has enormous costs, but it's not taught in school because Computer Science and software development are almost entirely different things. Commented Jan 3, 2019 at 17:51

Most of what you describe is not really (important) architecture - good naming and good class design is something which should be second nature to you. This will simply get better the more you code. Most helpful for such concerns is usually pair programming - it helps to clarify such problems and helps you learning how to this efficiently.

Where architecture is necessary is BEFORE the project:

  1. Gather the exact requirements and non functional requirements (how many requestes/second do I need to support?). Any missmatch in this phase will lead to coding hell - integrating missed ideas after the fact is time consuming, annoying and sometimes impossible. I know this is not fun as coding, but trying to get the code to do something it was not designed for is even less fun.

  2. If appropiate, define the bounded contexts of your system and make sure you have your vocabulary straight, e.g if the business talks about "Frobbels" make sure you name classes /interfaces etc. with "***Frobbels". Sounds trivial, but if you talk about workflows, while the business talks about operations, translating gets annoying very fast.

  3. If you work with multiple persons / teams describe your interfaces early and make sure all assumptions and problems are understood by everyone - if you do not have a shared context, integration will be "fun". E.g. you build a banana picture generator, but your frontend-dev needs an apple picture generator. Or you build something which can answer 100 requests/second, but 10000 r/sec are needed.

Note: this is heavily influenced by my work on a microservice architecture. How the serves is build internally, CAN be architected, too - but most of the time it is way less important than getting the big picture right.


I'm not going to throw a bunch of terms and abbreviations at you (most of which are hardly agreed upon by the majority of coders/software engineers). Instead, consider the following:

  1. You're learning - you're not wasting time, you're trying out different approaches and learning what works. You can do this without planning ahead a lot, by diving into a problem with the first solution that comes to mind and changing it if or when it doesn't work. If it does work well, great! You've found a simple solution to a problem. Simple solutions are just fine if they work well, and sometimes they are good enough.

  2. Everything is a tradeoff - you can design the same system in many different ways, trading off time and space, complexity and flexibility, abstraction and readability, or any one of many tradeoffs that are possible. No solution is perfect in every way and no rule is without exceptions in software engineering. Whoever tells you otherwise is either naive or selling something.

  3. As a recent graduate, coding and debugging can be very exciting, but this will wear off with time, and the skills you're learning now will serve you well when it does.

  4. I would argue that building software is more art/craft than engineering. Great art isn't just about the individual brushstroke, but rather about high-level decisions and tradeoffs made by the artist/craftsman.


I'll try to answer this question coming from a webdevelopment standpoint (meaning: coming from a field where people agonize over architecture a lot). I'll start with explaining why people care about architecture and will then outline ways to get past the architecture part more quickly.

Architecture does two things for your code:

  1. It makes it easier to understand your code for you and others.
  2. It helps structure your code in a way that makes it easier to extend and integrate it.

A code style makes it easier to read a specific portion of the code, by providing you with conventions that you can recognize and use to navigate through it. Likewise a good architecture helps you to identify where you will actually find the code that handles a specific feature. For example, in most web projects the architecture closely relates to how folders and files are sorted. On the flipside, a good architecture should actually help you think less about the code, because it should allready have a intuitive place where any piece of code belongs to.

In addition, a good architecture provides a shorthand for avoiding many of the pitfalls that could keep your code from being used easily. Again, if you make a architecture decision, it should set up a convention that helps you think less about how to write code.

Now the part that you are actually here for:

What can you do get through the architecture part more quickly:

  1. Don't do it

As many answers have allready pointed out. First ask yourself if you actually need architecture. If you won't have much code (and you can be reasonably sure that the project won't grow in the near future), you can just skip the architecture part and cobble together something that simply works. HOWEVER, if you are early in your career, I'd use the opportunity to practice whenever you can. At some point you will be doing bigger projects, and at that point it's probably to late to learn.

With that out of the way, what can you do to make architecture less painfull:

  1. Do it early
  2. Steal
  3. Learn / Stick to it
  4. Don't overdo it

Deciding on a architecture should be an early part of the planning process. As soon as you have an idea of what kind of app/program/website you will be making, you should think about what kind of architecture would support this.

At this point it's time to shamlessly steal. There is a lot of literature out there about how to properly set up a program architecture, and a astounding amount of use-cases is covered by these existing architecture prototypes. You should learn a rough overview of what kind of architectures exists out there, even if you don't know how to implement them.

If you have settled on a kind of architecture, then stick to it. For the most part, architecture decision should be intuitive and only take a few seconds after the initial setup. A lot of this comes down to experience.

Lastly, don't overthink stuff. You give the example of wether something should be public or private, and the truth is, that it probably doesn't matter if you make everything public. Yes, you shouldn't do it this way, and to many of these small mistakes will pile up after a time, but at the end of the day it probably won't kill your project either. First and foremost create working software!

(PS: That last sentence is no excuse for being lazy. Prioritizing working software doesn't mean you won't have to learn good coding someday.)


Answer is very simple,

  • Create a prototype (Time boxed)
  • Refactor (spend as much time as you want or have based on wide range of factors)

When you are creating prototype the focus should be on Minimal Viable Product, and when you are refactoring, focus should be on making your project or solution scalable.


How can I more quickly get through the architecture phase and onto the coding and debugging phase, which I enjoy?

By relegating this task to (or asking for help from) your more experienced coworkers.

You simply lack the experience necessary to quickly make such decisions. Uni got you a nice theoretical background, but it only gets you to a starting line. There is no other way to judge a given architecture in a given situation than by knowing how similar architectures had behaved in similar situations in the past.

Working with people who are better at the job than you is the fastest way to learn things. If you have nobody senior to turn to, you need a better job. "Better" as in "suiting your needs better". The need of knowledge and experience is your most dire need at this moment, as proven by your dilemma. You enjoy the the coding and debugging phase? Sounds like a perfect junior. But a junior needs senior's guidance. That's the point of those job descriptions. Strangers on the internet can only help you so far, you need a mentor.

  • I think this is good answer but I would suggest changing "Working with people who are better than you" to "Working with people who are more experienced than you". 'Better' can be interpreted in so many different ways as you demonstrate in the next sentence.
    – JimmyJames
    Commented Jan 3, 2019 at 15:13
  • @JimmyJames I've changed to "better at the job". Because the experience is only a part of it.
    – Agent_L
    Commented Jan 3, 2019 at 15:35
  • I don't disagree with that in general and it's precisely the reason I think 'better' isn't necessarily the right word here. I think for the OP, they are swirling because they have no context of the process of design. Even a bad designer/architect can help with that and is technically 'better' than the OP. But once the OP understands the job, they may be 'better' than the mentor. So it's not that your answer is incorrect, there's just a lot of nuance that isn't obvious from the use of the term 'better'.
    – JimmyJames
    Commented Jan 3, 2019 at 18:17

I see some serious issues with this question. Let's start.

How to stop wasting time designing architechture

This question is rather loaded. Also, you don't design architecture. You architect. Architecture and design are complementary and related activities, but are not the same, even if they might overlap.

Similarly, in the same way it is possible to waste time doing architecture (by over-architecting), you can also waste time over-designing and over-coding (by coding stuff in a manner far more complex than necessary, or by failing to code for the things that are required.)

Proper architecture aims to prevent that waste in coding. It does so by limiting, narrowing and documenting the possible ways a complex system is to be 1) designed, 2) coded and test it, 3) delivered, 4) maintained, 5) recover from failure, and 6) ultimately decommissioned.

My experience has been that people who just enjoy coding, they just code without any thought of how a system is to operate and maintained on the long run, moving to the next hot potato leaving some poor soul to maintain an ugly golem.

But I digress...

This is the thing: For systems simple enough, architecture is self-evident and emanates from sound design and implementation practices.

It is only for large systems that involves a rather large number of people or system-level software that does very complex stuff that require explicit architecture.

I have recently graduated from uni and started working as a programmer. I don't find it that hard to solve "technical" issues or do debugging, things that I would say have 1 solution.

That is the minimum required for this profession, and I'm glad you have no problem doing them (I'd be worried if you did.)

But there seems to be a class of problems that don't have one solution

Those are the bread and butter of our profession, the type of problems for which employers are willing to pay our (typically) far-above-average salaries.

As a matter of fact, problems worth solving are those that can have more than one solution. Real world problems, they are like that. And the world require our expertise, as software developers, to come up with acceptable trade-offs.

-- things like software architecture.

The architecture of things is an inevitable characteristic of complex system, be them virtual/software or in the concrete world. Every system that operates, that takes input and produces output, it will be complex and will have an architecture.

When we develop software for such systems (a banking system, a power monitoring system, a ticket sales system, etc), we aim to produce a piece of software that mimics the functions and requirements of such a system.

We just cannot simply wing it and code it cowboy style. We need some sort of architecture. This is particularly true if the project requires dozens of engineers, if not more.

These things befuddle me and cause me great distress.

That is ok. It is not an easy subject to learn or teach, not without a lot of practice.

I spend hours and hours trying to decide how to "architect" my programs and systems. For example, do I split this logic up into 1 or 2 classes, how do I name the classes, should I make this private or public, etc. These kinds of questions take up so much of my time, and it greatly frustrates me. I just want to create the program, the architecture be damned.

Unfortunately, that's not software architecture.

It's not even design, but just coding. I'll provide some suggestions at the bottom of this post.

How can I more quickly get through the architecture phase and onto the coding and debugging phase, which I enjoy?

I'm having a hard time finding a way to answer this, for it is rather emotional.

Are we trying to get a job done, or are we trying just to enjoy the practice? It is great when both are one and the same, but in real life, many times they aren't.

It's great to do things we enjoy, but in a profession as complex such as ours, to focus just on what we enjoy, that's not conductive to have a fruitful career.

You won't progress, you won't mature or acquire new knowledge.

There's this saying in the Army, "embrace the suck."

Others phrases have similar advise. "If it doesn't suck, it's not worth it" and my favorite, "If it sucks (and it is important), do it until it stops sucking."

My recommendations:

It seems to me that you are still struggling to understand the differences between

  1. coding (how to code your classes, modules or what not, naming conventions, access visibility, scope, etc),

  2. design (how many tiers, front-end/back-end/db, how each communicates, what goes where) and the implicit architecture decisions that comes from the design of simple systems,

  3. architecture (as found in complex systems requiring thousands, if not hundreds of thousands of man-hours.)

So I would suggest you delve deeply into the first subject (coding) to take it to the next level.

Clean Code

Robert "Uncle Bob" Martin's "Clean Code" is a good place to start.

Software Cohesion

Additionally, I'd suggest you get familiar with a specific Object-Oriented software metric called LCOM or rather LCOM4.

It can get rather mathematical and it's not bullet-proof, but your goal should be to empirically understand and detect (or eye-ball if you wish) if a class is cohesive or if it lacks cohesion.

http://www.aivosto.com/project/help/pm-oo-cohesion.html#LCOM4 https://www.computing.dcu.ie/~renaat/ca421/LCOM.html

Software Principles

This goes closely related with the "Single Responsibility Principle" or SRY that we should all be familiar with. SRY is one of the 5 "SOLID" that we all need to be familiar with if we are to become proficient at coding.

As we move through SOLID principles, we also need to familiarize ourselves with "GRASP" principles, which govern, or rather guide how we code classes.

Additional Books

Lastly, I'd also suggest the following:

  • "Refactoring" by Martin Fowler and Ken Beck would be the next book I'd read in this list.

  • "Design by Contract, by Example" by Richard Mitchell, Jim McKim and Bertrand Meyer (the later of Eiffel's fame.) This book is out of print, but you can find cheap, used copies in Amazon.

With this, you should get a good grasp of how to start coding and design, and with practice, to move and master (or at least grasp) software architecture.

I'm sure there will be other professionals who will add, subtract or object to these suggestions. They'll come up with other suggestions, likely validated by their own experience.

All I can say is this - there are no shortcuts.

All the best.


There's a lot of information here and frankly TL;DR. There's one main thing that I think people get wrong when trying to learn how to design a system: they try to think about it in the order that the work will be done. Instead, you need to work backwards. That is, the main goal of design/architecture is to determine what the end result should be.

As an analogy, consider the architecture of a home. An architect doesn't start out asking themselves questions like: "how many windows should this house have?", "where should the first brick be placed?". Those implementation details are not the design, they are derived from the design. The architure starts with a vision, maybe a sketch of what the finished home might look like. Is it a single-family home, a duplex? Is it a luxury home or an easily affordable one? Likewise, whether variables are private and whether you split a class has very little to do with architecture.

Start first with figuring out what the goals of your design are. For example, is this a one-off solution? Is it going to be expanded upon and revised and maintained over decades? The answer to that will indicate very different designs and that's the point of architecture. Once you have figured out what you need to do, the details of the design follow naturally. Not that these details are obvious or easy but it's the high-level plan that these choices are based upon.


How to judge how much time you should devote to architecturing any piece of software before getting a write-compile-test loop of some kind is pretty straightforward: enough information to fit in your head, and no more than that. Unless the project you are working on mandates a stricter methodology that is. In which case as a beginner most likely you should be reading an architecture document, not writing it.

As for naming things, to me that's part of "writing" but it is undoubtedly a very important part of programming: don't hesitate to think hard about how you name things, and to think harder the greater the scope of the name.

Finding the right names, the right architecture, the right modularity and the right abstractions is part of experience which you will gain by making mistakes. Over the years I've written a program doing the same thing about five times and the code was very different each time because every past iteration gave me hints at a better design.

Not the answer you're looking for? Browse other questions tagged or ask your own question.