Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
What is the difference between module vs. component design?
I'd like to share my idea about this difference.
Both component and module are used to refer to a group of functions or a part of a function. Module is more logical, for example: module Finance, module HR, module Manufacturing... in ERP system. On the other hand, component is more physical. In software, it can be a dll, ocx, exe,...
There is no criteria to measure which one is greater than the other. One component can contain list of modules, and one module also can contain many components. Components are used to model a system in technical view, and module is used to model the system in function view ( functionalities of the system)
Components and modules are too often confused with each other. They
are, however, not the same, and the implications of one, does not
necessarily hold for the other.
Modularity is the partitioning of code into modules of related
functionality. In many programming languages, a module is simply a
source file. It is common practice that if the source file grows too
big, you can split it into two or more source files, and put these
into a new directory; while a directory is often not called a module,
this kind of decomposition is still modular.
A component, on the other hand, can be composed in different ways with
other components to form different programs. That is, there is a
separate composition stage, where real people decide which components
should be used together.
I have seen component design being used to enforce some notion of hard
modularity. This approach cannot be recommended because of the rather
significant overhead of composition: the composition complexity grows
polynomial with the number of components. And the number of
components grows linearly with the number of functionality groups,
because once you get started with modularity by component
decomposition, you force yourself to create a new component whenever
you would otherwise just need a new module, because that new module
would otherwise not really belong anywhere. At a 100 components, the
composition overhead became a full-time job, and each composition
iteration would take up to a couple of weeks, despite numerous
automation efforts. This significantly impeded development.
My simplest recommendation is to stay away from components if at all
possible; well-knowing that components may sometimes be a necessity.
For instance if multiple independent organizations are involved in a
project, one component for each organization seem acceptable.
It is a matter of taste, how fine grained your decomposition into
modules should be, though everyone agrees that modularity is a good
thing.
If I know the name of a function, my editor will find it soon enough.
On the other hand, if for some reason I don't know the name of a
function (or a class for that matter), modularity becomes more
important.
I would expect the later case, to only be an issue for functionality that
you can experience from using the program, so try to make the
decomposition of your program into modules reflect an intuitive
decomposition of the behaviour of your program into areas of
functionality.
There is a reference in the «OSGi in Action» book, which, I believe, explains the differences well.
Modules vs. components
Doesn't it sound like modules and components have a lot in common? They both provide stuff to each other and consume stuff from each other. They're also packaged as independent deployment units. Couldn't these two be considered one and the same or at least be combined? Yes, they could, but components and modules serve different purposes and are somewhat orthogonal (they're not completely orthogonal, because components are made from code that can ultimately be packaged into modules).
Modules deal with code packaging and the dependencies among code. Components deal with implementing higher-level functionality and the dependencies among components. Components need their code dependencies managed, but they technically don't need a module system to do it (often it's us programmers doing it via the class path).
A good summary is that you can think of modules as dealing with static code and compile-time dependencies, whereas components deal with instances and execution-time dependencies.
— «11.1.1 What are components?», «OSGi in Action» (page 347).
If you mean module in the sense of modularity there is a definition in the IEEE Standard Glossary of Software Engineering Terminology:
"Modularity is the degree to which a system or computer program is composed of discrete components such that a change to one component has minimal impact on other components."
And Dr. Bertrand Meyer stated five criteria for modularity:
Decomposability of the problem into sub-problems
Composability of modules to produce new systems
Understandability of a module in isolation
Continuity - small changes have localized effects
Protection - fault isolation
For digital development and UI consideration (HTML/CSS/JS), I use this approach to ensure I'm staying organized and thinking before doing. Has proven to create cleaner, more organized code which translates nicely to doing more with less.
In a typical stylesheet, I'm currently setting up like this:
/* Style Guide – Mobile First
1. =Setup
2. =Modules as independent units made up of components
3. =Components as group of reusable code containing more than one element
4. =Classes
5. =Responsive as enhancement
*/
Modules as independent units made up of components: Header, Footer, Sections, Articles, Aside, etc. A house is made up of many rooms, all with special styles and functions to create an independent whole.
Components as a group of reusable code containing more than one element: Unordered Lists, Quotes, Cards, Tables, etc.
I wrote a fuller explanation you can read here.
Hope this helps!
Component is a runtime entity (can be made up of modules), independent runnable unit
Module is a partitioned system into implementation units, independent task assignment. Modules might or might not be a component
In my view, Module and Component are all just a couple of functions and assets.
And the different between them is:
Component has business logical and module not.
For example,this text input area is just a Module, but when there was some post api called,it become a Component. you can put a module everywhere and it will work fine, but Componet just can be used in a specific page or view(coz it has a specific api call)
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
What are conventions for the grouping of subroutines and functions into standard modules with the MS Access VBE? I can find plenty of information on nomenclature and the function of subroutines and functions within modules, but nothing on how to group subroutines and functions into standard modules.
Currently, I have two total standard modules-- one called "Subs" and one called "Functions", each containing hundreds of lines of code that it is becoming a drag to navigate. What guidelines can I use to make it better?
I try to keep reusable Subs and Functions appart from application specific ones.
I try to group those by functionnality. This way I have a module I can import when dealing with text files import/export, another one for XML stuff, another one for browsing files or folders, extracting the folder from a full path and so on.
Also, I generally export modules to .bas files (right click on module, then Export) which I can reimport in other apps.
What you're after, is called abstraction.
It doesn't matter at all that a member is a Sub, a Function, or a Property (please don't say you have a Properties module...). What you care about is its purpose.
Name things for what they're used for, and regroup public members by purpose. Keep the public members' implementations simple, at a relatively high level of abstraction.
In plain English, this means if you have a procedure that makes coffee and fetches a mug, knows where to get the water, the milk, the cream, the sugar, the hazelnut and French vanilla aromas, knows how much to pour of everything, stirs it and serves it (or whatever it is that you do in hundreds of lines of code), then you have a procedure that's doing way too many things.
Split it up. Break it down into small steps, each more specialized (i.e. at a lower abstraction level) than the previous.
Public Sub MakeCoffee()
Dim selectedCoffeeType As CoffeeType
selectedCoffeeType = PickCoffeeType
Dim selectedSize As CoffeeSize
selectedSize = PickCoffeeSize(selectedCoffeeType)
GrindGrains selectedCoffeeType
Infuse selectedCoffeeType, selectedSize
AddExtras
End Sub
Notice this MakeCoffee procedure couldn't care less about whether there's water in the machine, or whether milk needs to be lathered, whether there are cups of the selected size available, whether there's grains for the selected type, how much sugar and/or cream to pour in, or about any other irrelevant details: it lets you pick a type and a size, and uses that information to do its deed.
The details are at a lower abstraction level, implemented under that procedure, in Private Function and Private Sub procedures. They're underneath it, because they're closely related, and if you read the module top-to-bottom, it's telling you a story that goes from very high-level to very specialized and detailed - there's never a need for a 200-liner procedure.
Now another module comes along, and you need a vending machine that sells chips and colas (or bio sandwiches and bottled water). Same thing: abstraction determines how things split up.
Then you need the coffee machine to implement a payment functionality. Are you going to copy the existing code from the vending machine? Call into the vending machine's private procedures from the coffee machine's code? Luckily you can't do that. No, you'll extract a class and encapsulate the payment module functionality into its own specialized object, and both the coffee and the vending machines can use it.
And if you use Rubberduck, then you can put #Folder annotations in each module, and actually organize your modules into folders and sub-folders that you can browse with the add-in's Code Explorer feature - so you have absolutely no reason to fear having "too many modules".
Thanks so much for your feedback, #Mat's_Mug and #iDevlop. Your respective abstract explanation and more concrete response both moved me toward the answer I was looking for.
It seems like both of you are suggesting, too, what my fruitless googling before asking this made me suspect, and what #Darren_Bartrup-Cook alluded to above-- there is no formal structure for organizing modules, and appropriate structure can very widely from one database to another. Correct me, please, if my takeaway is wrong, but what I've gleaned from what both of you have said is that the general principles to pursue are:
to find groupings that are meaningful and useful within your own code (better to risk grouping too small than too big, maybe?)
to keep implementations at a high level of abstraction, for the readability/ease of debugging the code
There is plenty of documentation out there that talks about design patterns (e.g. Visitor), SOLID (Single Responsibility etc), KISS (Keep it Simple, Stupid), tiered design etc.
One thing I don't fully understand is how to decide when a new project/DLL is required when extending an application. Is there any criteria that is used?
For example, System.Windows.Forms (http://msdn.microsoft.com/en-us/library/system.windows.forms.containercontrol.aspx) is part of System.Windows.Forms.dll yet it derives from System.MarshalByRefObject, which is part of mscorlib.dll.
You're mixing up assemblies (DLLs) and namespaces.
Assemblies are the binary files which contain the implementations of classes, etc.
Namespaces are just a way to organize classes, enums, etc. into logical groups, to prevent from having every class accessible from every level, and prevent naming conflicts (eg. System.Windows.Forms.Timer and System.Threading.Timer).
System.Windows.Forms doesn't derive from System, and System doesn't live solely in mscorlib.dll. Anyone can put anything in the System namespace - even you could do it. It's just a sub-namespace of System.
There are several reasons for breaking a subset of code out into a separate assembly. A big one is re-usability. If you have some common controls or utilities, you can maintain it in its own DLL and use it across projects without copy-and-pasting of code.
Don't confuse tiers with layers. Layering your code is almost always a must. Splitting your code out into separate physical tiers, however, is something that you usually don't want to do until you actually need to (following the KISS principle).
If you layer your code properly, then when the time comes that you need to break it out into separate tiers, doing so should be a very painless process. If, however, you never layered your code properly you'll find that splitting out the tiers will be very difficult.
As a simple example, lets say you create a login form and lets say you put all the logic to gather the system information, access the database, validate the user credentials, and build the permissions, all directly into the WinForm class. The code I just described has only 1 layer and it has only 1 tier. If you then found yourself needing to create a web-based login page using ASP.NET, you would find it very difficult to reuse that existing code. With the web based login, you'd want to at the very least, separate the UI logic from the business/data access logic, but because it's all directly in the WinForm class, it's all unusable without re-factoring the code.
Now, let's say, instead of putting all that code in the form, you took the time to layer it properly. Let's say you broke out all of the code that accessed the database about put it all into data access classes. And then you put all of the business logic code put it all in business classes. At that point, the actual code in the WinForm class should be limited to doing nothing but UI related logic such as handling control events, setting labels, etc. In this second example. you still only have 1 tier, but you have three distinct and independent layers (viz. UI, Business, Data Access).
If you had already layered your code like that, then when the time came that you needed to reuse it in the web-based project, you could easily move the business and data access layers into a class library (dll) and then reuse them in the ASP.NET project for the server-side tier.
Breaking your code into separate class libraries is only typically necessary in two situations:
You need to reuse the code in multiple projects
You need to divide your project into multiple tiers
Even if you put all your code in a single project, as long as it is well-layered, it will be very easy to split the project up into multiple class libraries when such a situation arises. So the big design issue is not how many DLL's you have. Rather, the big design issue is how many layers you have. Once you have the code layered, it will be easy to move it around between different projects as necessary.
In practical terms, even when you don't need to reuse the code between projects nor support n-tiers, you may still legitimately choose to divide your layers into separate class libraries. It may make sense to do so purely for organizational purposes, or for consistency. For instance, if another developer comes behind you and sees classes in a class library called "MyCompany.Feature.Business", they can safely assume that those classes are all part of the business logic layer. In that way, breaking your code up into separate class libraries can be self-documenting.
There are other reasons too, for putting code in dlls. For instance, it makes it easy to support plug-in architectures or to make it easier to update one part of the application at a time.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
I do know some advantages to classes such as variable and function scopes, but other than that is just seems easier to me to have groups of functions rather than to have many instances and abstractions of classes. So why is the "norm" to group similar functions in a class?
Simple, non-OOP programs may be one
long list of commands. More complex
programs will group lists of commands
into functions or subroutines each of
which might perform a particular task.
With designs of this sort, it is
common for the program's data to be
accessible from any part of the
program. As programs grow in size,
allowing any function to modify any
piece of data means that bugs can have
wide-reaching effects.
In contrast, the object-oriented
approach encourages the programmer to
place data where it is not directly
accessible by the rest of the program.
Instead the data is accessed by
calling specially written functions,
commonly called methods, which are
either bundled in with the data or
inherited from "class objects" and act
as the intermediaries for retrieving
or modifying those data. The
programming construct that combines
data with a set of methods for
accessing and managing those data is
called an object.
Advantages of OOP programming:
MAINTAINABILITY Object-oriented programming methods make code more maintainable. Identifying the source of errors is easier because objects are self-contained.
REUSABILITY Because objects contain both data and methods that act on data, objects can be thought of as self-contained black boxes. This feature makes it easy to reuse code in new systems.Messages provide a predefined interface to an object's data and functionality. With this interface, an object can be used in any context.
SCALABILITY Object-oriented programs are also scalable. As an object's interface provides a road map for reusing the object in new software, and provides all the information needed to replace the object without affecting other code. This way aging code can be replaced with faster algorithms and newer technology.
The point of OOP is not to 'group similar functions in a class'. If this is all you're doing then you're not doing OOP (despite using an OO language). Having classes instead of just a bunch of functions has a side effect of 'variable and function scopes' that you mention, but I see it just as a side effect.
OOP is about such concepts as encapsulation, inheritance, polymorphism, abstraction and many others. It is a specific way of software design, a specific way of mapping a problem to a software solution.
Grouping functions in a class is by no means the norm. Let me share some of the things I have learned through experimentation with different languages and paradigms.
I think the core concept here is that of a namespace. Namespaces are so useful that they are present in almost on any programming language.
Namespaces can help you overcome some common problems and model various patterns that appear in many domains, e.g., avoiding name collisions, hiding details, representing hierarchies, define access control, grouping related symbols (functions or data), define a context or scope ... and I'm sure there are more applications.
Classes are a type of namespace, and the specific properties of classes vary from language to language and sometimes from version to version of the same language, e.g., some provide access modifiers, some do not; some allow inheritance from multiple classes, others do not. People have been trying to find the magic mix of features that will be the most useful and that in part explains the plethora of available options in different programming languages.
So, why use classes, because they help solve certain kinds of problems in a way that seems natural or maybe intuitive. Every time we write a computer program we're trying to capture the essence of the problem and if the problem can be modeled by using some of the patterns mentioned above then it makes perfect sense to use those features of a language that help you do that.
As the problem becomes better understood you might realize that certain parts of the program could be better implemented by using a different paradigm/feature/pattern and then it's time for refactoring. Most programs I have had the chance to work on keep evolving until either the money/resources run out or when we arrive at the point of diminishing returns, many times you have something that's good enough for now and there's little incentive to keep working on it.
It's not the norm, it's just one way of doing it. Classes group methods (functions) AND data together, based on the concept of encapsulation.
For lager projects it often becomes easier to group things this way. Many people find it easier to conceptualizes the problem with objects.
There are many reasons to use classes, not the least of which is encapsulation of logic. Objects more closely match the world we live in, and are thus often more intuitive than other methodologies. Consider a car, a car has properties like body color, interior color, engine horsepower, features, current mileage, etc.. It also has methods, like Start (), TurnRight(.30), ApplyBrakes(.50). It has events like the ding when you open your car door with the keys in the ignition.
Probably the biggest reason is that most applications seem to have a graphical component these days and most of the libraries for graphical user interface are implemented with object models.
Polymorphism is probably a big reason, too. The ability to treat multiple types of objects generically is quite helpful.
If you are a mathematician, a functional style may be more intuitive, ML, F#. If you’re interacting with data in a predictable format, a declarative style would be better like SQL or LINQ.
In simple words, it seems to me that (apart from everything everyone is saying) that classes are best suited for large projects, especially those implemented by more than one programmer to facilitate keeping things tidy; as using functions in such situations can become rather cumbersome.
Otherwise, for simple programs/projects that you would implement yourself to do one thing or another, then functions would do nicely.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I recently had my code reviewed by a senior developer in my company. He criticized my design for using too many classes. I am interested to hear your reactions.
I was tasked to create a service which produces an xml file as a result of manipulating 3 other xml files. Let's name these aaa.xml, bbb.xml and ccc.xml. The service works in two phases. In phase one it scrubs aaa.xml against bbb.xml. In the second phase, it merges the product of phase one with ccc.xml to produce a final result.
I chose a design with three classes: an XmlService class which used two other classes, a scrubber class and a merger class. I kept the scrubbing and merging classes separate because the both classes were large and featured distinct logic.
I thought my approach was good because it kept my classes small and cohesive. My approach also helped to control the size of my test class.
The senior developer asserted that the scrubbing and merging classes would only be used by the XmlService class, and should therefore be part of it. He felt this would make the XMLService cohesive and this is what being cohesive means according to him. He also feels that breaking up classes this way makes them loose cohesiveness.
The irony is I tried to break these classes to achieve cohesiveness. What do you think? Who is right or wrong? Are we both right? Thank you for your suggestions.
If you follow the single responsibility principle (and based on the tone of your question, I think you do follow it), then the answer is clear:
A class is too big when it does more than one thing; and
A class is too small when it fails to fulfill its purpose.
That's very broad and indeed subjective -- hence the struggle with your colleague. On your side, you can argue:
There's absolutely no problem in creating additional classes -- It's a non-issue, compile-wise and runtime-wise.
The current implementation of the service may suggest that these classes "belong" to it, but that may change.
You can test each functionality separately.
You can apply dependency injection.
You ease the cognitive load of understanding the inner working of the service, because its code is smaller and better organized.
Furthermore, I think your boss has a misguided understanding of cohesion. Think of it as focus: the narrower the focus of your program, the higher the cohesion. If the code on your satellite classes is merged within the service class, the latter becomes less focused (less cohesive). It's generally accepted that higher cohesion is preferred over lower cohesion. Try to enlighten his/her view about it.
Cohesion is a measure of how strongly related is the functionality within a body of code. That said, if merging and scrubbing aren't strongly related, including them both in the same class reduces cohesion.
The Single Responsibility Principle is also worth mentioning here. Creating a class for the sole purpose of scrubbing and another for the sole purpose of merging follows this principle.
I'd say your approach is the better of the two.
What would you name the classes? ScrubXml and MergeXml are nice names. ProcessXML and ScrubAndMergeXml aren't, the first being too general and the second having a conjunction. As long as none of the classes rely at all on the internals of one or the others (i.e., low coupling), you've got a good design there.
Names are very useful in determining cohesion. A cohesive module does one thing, and therefore has a simple specific name. A module that does more than one thing is less cohesive, and needs a more general or more complicated name.
One problem with merging functionality in X into Y if X is only used by Y is the reductio ad absurdam: if your call graph is acyclic, you'll wind up with all your functionality in one class.
As someone who is coming back from the GodClass building fest of several years in duration, and now trying very hard to avoid that mistake in the future; the error of making a 6000 to 10000 line single source unit with a single class, with over 250 methods, 200 data fields, and some methods over 100 lines, the single responsibility principle looks like something worth defending against the predilections of your unenlightened supervisor.
If however, your supervisor and you are disagreeing over a matter of whether 2000 lines of code belong in one class or three, then I think you're both closer to sane, than I was. Maybe it's a matter of scale and perspective. Some object oriented programming aficionados like a certain "Coefficient of Standalone" per class, in direct violation of the generally understood ideas about how to improve cohesion and minimize coupling.
A set of 3 classes that work well together is, objectively, a more object-oriented system, than a single class that does the same thing. one could argue that if you write an application using only one class, that the application is not really object oriented at all.
If the scrubber and merger are not meaningful outside the context of the main class, then I agree with your reviewer, particularly if you've had to expose any implementation details in order to allow this separation. If you're using a language supporting nested private classes or something similar, that might be a reasonable alternative to maintain the logical separation without exposing implementation details to outside consumers of the main class.
This is a very subjective area, and will be different depending on coding and style guidelines, and who approves your code.
That said, if your defense of your design didn't hold up, and your senior team member still insisted on merging your classes, then you have to compromise:
You've already got the logic separated out. Write the one service class and keep the methods separate like other good design, and then write a glue method. Add some comments above each method explaining how they could easily be partitioned to multiple classes if the need arises in the future.
I'm just wondering about large projects - say an airlines reservation system, how many classes/objects it is likely to have.
Objects: customer, airplane, airport, route, ticket, order. That's about all I can think of. The project will probably be hundreds of thousands of lines of code, so are there likely to be more classes (that do un-object related things)?
If so, how many classes are there likely to (roughly) be? How many objects (as per my list so not 10,000 customer objects, how many different names) are there likely to be?
There's really no magic formula for calculating optimal number of classes. The architecture you described above may create a very, very simple airline reservation system. As you continue to refactor, add more features, and accommodate special cases, you could end up with many more classes, e.g., MealPreference, CouponCode, Terminal, Gate, Airline, Baggage, BaggageTransfer, RainCheck, FlightUpgrade etc.
As you should (if you want to be agile), only code exactly what you need at the time, planning ahead for ease of extension. However, any project is going to grow in unanticipated ways over time.
For a real world airline reservation system? Thousands. Easily.
I'd guess around half of them are "infrastructure" classes - mostly related to persistence, logging, integration, etc. Maybe a few hundred domain classes (Airline, Airplane, Flight, Passenger, FrequentFlyer, MaintenanceSchedule, WeatherDelay, etc). And then another half of them would be UI related - controllers, views, view models, etc. to support both customer and internal apps.
The number of classes will be only statistical and it knowing it won't help you to establish any best practice, but I would say it can go to thousands of classes.
What it's important is to keep in mind the best practices and naming conventions, it is important to have a good package structure and name your classes according to its purpose, also keep in mind a high level of cohesion for your classes.
So other than satisfying your curiosity the number doesn't matter.
The number of classes is really relative to the design patterns and architecture you build.
For instance, with a simple console application that adds two numbers together, you can have anywhere from 1 to 10 (rough guess) based on the implementation and abstraction used.
You really can't judge how many "objects" an application is going to contain, without knowing the architecture and patterns.
I agree that it is very dependent on a lot of things; code language, application architecture, number of 3rd party extensions (which typically contain a lot of classes that don't actually ever get called by the app, but are included with .dll or .jar files), and a lot on the habit of the developer and if they tend to use giant monolithic classes, or break down everything into an interface, abstract, simple/stub, and real implementation.
However if your just looking for statistics, I was recently working on a large project for General Motors that had I'd say roughly 3000 classes, plus 200 JSP pages, and a few dozen CSS and JS files supporting the UI. Plugged into that you have DB drivers, Spring framework, a couple apache commons libraries, Hibernate ORM, Mule, JSTL, probably some other core components... the web server itself...
This is entirely dependent on the abstraction you use. In my experience, the closer you follow the problem domain (the closer you try to make your code read like what a business person would say), the more classes you'll have.
All the other answers you've received are wise: basically, "It depends."
But in another sense, there is an optimal number of classes you should have for a given number of methods; that is, given a number of methods, there is a specific number of classes (within a non-hierarchical encapsulation context, and to a close approximation) which minimises the potential structural complexity of those methods. (The actual number is given by the second law of encapsulation, and is equal to the square root of the number of methods divided by the number of public methods per class).
So then the question becomes: how many methods will you need? By analogy to the above, in which methods are encapsulated within classes, so blocks of code are encapsulation within methods, and so the number of methods is fixed by the same second law above.
So then the quesiton is: how many code blocks will I have?
That's answered by the other responses you've received: it depends.
For more, see Encapsulation Theory here:
www.EdmundKirwan.com
Regards,
Ed.